<?
if (@$argv[1]==='--test=CommonSense' && !@$_SERVER['REQUEST_URI'] && !defined('WS_WEB')) {
define('WS_CONSOLE',1);
define('WS_TEST_COMMON_SENSE',1);
}
else {
define("WS_WEB",true);
}
require_once( "common/WebInit.php" );
require_once( "common/FilterCats.php" );
require_once("WikiAccess.php");
require_once("WikiSenseLocalizer.php");
define('COMMONS_LINK_PATTERN','/\[\[ *:?commons:([^\|\:\]]+:)*([^\]\|]+)(\|[^\]]*)? *\]\]|\{\{ *(Commons[12]?|Commons? ?Cat|Commons ?Category|Commons-inline|Catlst commons|Cms-catlist-up) *\| *([^\|\:\}]+:)*([^\|\}]+)( *\| *([^\}]*))? *\}\}/smi');
define('CATEGORY_REDIRECT_PATTERN','/\{\{ *(seecat|catred|category_redirect|category redirect) *\| *(.*?) *\}\}/is');
$commonsLicenseCategories= array(
'GFDL',
'GPL',
'LGPL',
'Public_domain',
'PD',
'PD-self',
'PD-user',
'PD_Old',
'PD_Art',
'PD_US',
'PD_US_Government',
'PD_NASA',
'PD_US_Military',
'Patents',
'Russian_official_symbols',
'PD_Soviet',
'CC-BY-SA-2.5',
'CC-BY-SA-2.1',
'CC-BY-SA-2.0',
'CC-BY-SA-1.0',
'CC-SA-1.0',
'CC-BY-1.0',
'CC-BY-2.0',
'CC-BY-2.5',
'BSD_images',
'Copyrighted_free_use',
'Copyrighted_free_use_provided_that',
'Self-published_work',
'Unknown',
'Own_work',
'Incomplete_license',
'Unknown',
#much much more....
);
class CommonSensePage {
var $enwiki;
var $commons;
var $projects;
var $wikis;
var $mainWiki;
var $imageUses;
var $usedWikis;
var $keywordWikis;
var $hashCounter;
var $verbosity;
var $image;
var $imageInfo;
var $keywords;
var $keywordlang;
var $pageTitle;
var $pageInfo;
var $processed;
var $categoryBlacklist;
var $stripRedundant;
var $sqlDebug;
var $errors;
var $messages;
function CommonSensePage ( $lang, $image, $keywords = NULL, $keywordlang = NULL ) {
global $wsgCommonSenseText;
$this->messages= $wsgCommonSenseText;
$this->image= $image;
$this->imageInfo= NULL;
$this->hashCounter= 0;
$this->verbosity= 1;
$this->stripRedundant= true;
$this->connections = array();
if ($keywords) {
if (!is_array($keywords)) {
$keywords= preg_replace('/"(.*?)"/e','str_replace(" ","_",\'\1\')',$keywords);
$k= preg_split('/[\r\n]+/',$keywords);
$keywords= preg_split('"[/\.!\?:#,;|/\s]+"',$keywords);
if (sizeof($keywords>1)) {
foreach ($k as $s) {
if (preg_match('"[/\.!\?:#,;|/]+"',$s)) continue;
$keywords[]= str_replace(' ','_',$s);
}
}
$keywords= array_unique($keywords);
}
$this->keywords= $keywords;
$this->keywordlang= $keywordlang;
}
$this->enwiki=& WikiAccess::newInstance( 'en.wikipedia.org' );
$this->commons=& WikiAccess::newInstance( 'commons.wikimedia.org' );
#$this->commonsInfo= getWikiInfoFromDomain( 'commons.wikimedia.org' );
if (!$this->enwiki->wikiDB) {
$this->error($this->msg('db_connect_error_1','en.wikipedia.org'));
die();
}
if (!$this->commons->wikiDB) {
$this->error($this->msg('db_connect_error_1','commons.wikimedia.org'));
die();
}
$this->putDbConnection($this->enwiki);
$this->putDbConnection($this->commons);
$lang= strtolower($lang);
$this->projects= $lang;
$this->trace(2,"using projects $lang");
$ll= preg_split('!\s*[\s,;/|]\s*!smi',$lang);
$this->wikis= array();
$this->mainWiki= NULL;
$this->usedWikis= NULL;
$this->keywordWikis= NULL;
$this->imageUses= NULL;
$this->errors= array();
foreach ($ll as $l) {
if (!$l) continue;
$inf= getWikiInfoFromDomain( $l );
if ($inf && $inf->domain) {
$db = $this->getDbConnection( $inf );
$this->wikis[$inf->domain]= WikiAccess::newInstance( $inf, $db );
}
else $this->error($this->msg('unknown_project_error_1',$l));
}
if ( sizeof($this->wikis) === 1 ) {
$k= array_keys($this->wikis);
$this->mainWiki= $this->wikis[$k[0]];
}
#print_r($this->wikis);
#print_r($this->commons);
#print_r($this->enwiki);
$this->pageTitle= array();
$this->pageInfo= array();
$this->processed= array();
$this->sqlDebug= false;
$this->categoryBlacklist= array(
"Fundamental",
"Reference",
"ArticleType",
"CommonsRoot",
"Copyright_statuses",
"Image_sources",
"MediaType",
"Disambiguation",
"User",
"Other",
"Objects",
"Wikipedia_bots",
"Commons",
"Commons_maintenance",
"Images",
"Movies",
"Sound",
"Videdo",
"Unknown",
"Flickr",
"Animation",
"Illustrations",
"Image format",
"Images by text",
"Photos",
"Pictures_of_the_day",
"SVG",
"Featured pictures",
"Drawings",
"Audio",
"Spoken_wikipedia",
"Multi-channel_sound",
"Meyers_Blitz-Lexikon",
"Languages",
#THis list would be huge... find a better solution
"Commons-en",
"Commons-de",
"Commons-fr",
"Commons-es",
"Commons-pl",
"Commons-jp",
"Commons-zh",
"Commons-ru",
"Commons-nl",
#That'S OK on the commons, but often used differntly in WPs (pl "album" pages, etc)
"Photography",
#FIXME: this sucks - used for meta-stuff on most 'pedias, but not on commons :(
"Wikipedia", "Wikimedia", "Logos", "Stubs", "Lists",
#FIXME: a ton more of the below, in all the languages...
"Deletion requests", "Candidates for speedy deletion",
);
#TODO: filter out all the "main pages" (all languages)
global $commonsLicenseCategories;
$this->categoryBlacklist= array_merge($this->categoryBlacklist,$commonsLicenseCategories);
}
function putDbConnection($wiki) {
if (@$this->connections[$wiki->dbServerId]) return; //XXX: ping?
if (!@$wiki->wikiDB) throw new Exception("no wiki db");
if (!@$wiki->dbServerId) throw new Exception("no server id");
$this->connections[$wiki->dbServerId] = $wiki->wikiDB;
}
function getDbConnection($wiki) {
if (!$wiki) throw new Exception("no wiki specified");
if (isset($wiki->wikiDB)) return $wiki->wikiDB;
$server = isset($wiki->dbServerId) ? $wiki->dbServerId : $wiki->server;
if (!isset($this->connections[$server])) {
$w =& WikiAccess::newInstance($wiki); //HACK: don't really need a WikIAccess instance here...
$this->putDbConnection($w);
}
if (!isset($this->connections[$server])) throw new Exception("failed to get connection for server #"+$server);
return $this->connections[$server];
}
function msg($key) {
$args= func_get_args();
return call_user_func_array ( array(&$this->messages, 'msg'), $args );
}
function close() {
foreach ($this->connections as $id => $db) {
$db->close();
}
#$this->commons->close();
#$this->enwiki->close();
}
function stringValue($data) {
if (is_null($data)) $data= "<null>";
else if ($data===false) $data= "<false>";
else if ($data===true) $data= "<true>";
else if (is_object($data)) $data= get_object_vars($data);
if (is_array($data)) {
$s= "{";
foreach ( $data as $k => $v ) {
$s.= "$k => ".CommonSensePage::stringValue($v).", ";
}
$s.= "}";
$data= $s;
}
return $data;
}
function sqlTrace($sql) {
if (!$this->sqlDebug) return;
print "\n<p style='fount-size:72%'>".escapeHtml($sql)."</p>\n";
}
function trace($level, $msg, $data='@dummy@') {
if (!headers_sent()) return;
if ( $level <= $this->verbosity ) {
if ($data==='@dummy@') $data= '';
else $data= " (".CommonSensePage::stringValue($data).")";
if ( $this->hashCounter > 0 ) {
print "<br/>\n";
$this->hashCounter= 0;
}
print " ".str_repeat("–",$level)." ".escapeHtml($msg . $data) . "<br/>\n";
}
else if ( ( $level - 2 ) <= $this->verbosity ) {
print ". ";
$this->hashCounter+= 1;
}
flush();
}
function error($msg, $die = false) {
if ($die) die($msg);
if (!headers_sent()) $this->errors[]= $msg;
else {
print "\n<p class='error'>".escapeHtml($msg)."<p>\n";
}
flush();
}
function findCategories() {
$gals= array();
$cats= array();
$pages= array();
if ($this->keywords) {
$p= $this->findKeywordPages();
if ($p) $pages= array_merge($pages,$p);
}
if ($this->image) {
$p= $this->findImageUses();
if ($p) $pages= array_merge($pages,$p);
}
#print_r($pages);
$this->trace(1,"searching fro commons categories...");
foreach ( $pages as $p ) {
if (sizeof($cats)>10 || sizeof($gals)>10) {
$this->trace(2,"found enough entries, aborting search");
break;
}
if ($p['domain']=='commons.wikimedia.org') {
$this->trace(3,"direct match on commons: ".$p['title']."(".$p['namespace'].")");
if ($p['namespace']==NS_CATEGORY) $cats[]= $p['title'];
else $gals[]= $p['title'];
}
else {
$wiki=& $this->wikis[$p['domain']];
$this->processPage($wiki, $p['title'], $p['namespace'], $gals, $cats, 4 );
}
}
$this->trace(1,"post-processing");
$gals= array_unique($gals);
foreach ($gals as $g) {
$info= $this->loadPageInfo( $this->commons, $g, NS_MAIN );
if ($info && $info['categories']) {
$this->trace(2,"adding categories from gallery page $g",$info['categories']);
$cats= array_merge($cats,$info['categories']);
}
}
$cats= array_unique($cats);
$cats= array_diff($cats,$this->categoryBlacklist);
if ($this->stripRedundant) {
foreach ($cats as $c) {
$this->stripRedundantCategories($c,$cats,3);
}
}
return array(
'galleries' => $gals,
'categories' => $cats
);
}
function stripRedundantCategories( $root, &$cats, $depth ) {
if ($depth==0) return;
global $wsgFilterCatDB;
if ($wsgFilterCatDB && isset($wsgFilterCatDB['commons.wikimedia.org'])) {
$db = $wsgFilterCatDB['commons.wikimedia.org'];
$r = filter_categories($cats, $db);
foreach ($cats as $k => $c) {
if (!in_array($c, $r['new'])) unset($cats[$k]);
}
return;
}
$info= $this->loadPageInfo($this->commons,$root,NS_CATEGORY);
if (!@$info['categories']) return;
$this->trace(2,"stripping categories (parents of $root):",$info['categories']);
$info['categories']= array_diff($info['categories'], array($root)); //ugly - should not be needed.
$cats= array_diff($cats, $info['categories']);
#FIXME: this *may* strip *all* categories, if the structure contains loops.
foreach ( $info['categories'] as $c ) {
$this->stripRedundantCategories( $c, $cats, $depth -1 );
}
}
function findKeywordPages() {
$pages= array();
$this->keywordWikis= array();
$wikis= array();
$wikis['commons.wikimedia.org']= @$this->commons;
$wikis= array_merge($wikis,$this->wikis);
foreach ($wikis as $domain => $wiki) {
$this->trace(1,"looking for keywords on ".$wiki->domain." wiki");
$found= false;
foreach ($this->keywords as $ttl) {
$ttl= trim($ttl);
if (!$ttl) continue;
if ( $t= $this->getPageTitle( $wiki, $ttl, NS_MAIN ) ) {
unset($p);
$p= array(
'domain' => $domain,
'title' => $t,
'namespace' => NS_MAIN,
);
$pages[]=& $p;
if (!isset($this->keywordWikis[$wiki->domain])) $this->keywordWikis[$wiki->domain]= array();
$this->keywordWikis[$wiki->domain][]= $p;
$this->trace(3,"keyword ".$t." found on ".$wiki->domain);
}
if ( $t= $this->getPageTitle( $wiki, $ttl, NS_CATEGORY ) ) {
unset($p);
$p= array(
'domain' => $domain,
'title' => $t,
'namespace' => NS_CATEGORY,
);
$pages[]=& $p;
if (!isset($this->keywordWikis[$wiki->domain])) $this->keywordWikis[$wiki->domain]= array();
$this->keywordWikis[$wiki->domain][]= $p;
$this->trace(3,"keyword ".$t." found as category on ".$wiki->domain);
}
if (sizeof($pages)>10) {
$this->trace(2,"found enough keyword uses, stopping search");
break;
}
}
if (sizeof($pages)>10) break;
}
#print_r($pages);
return $pages;
}
function findImageUses() {
if (!is_null($this->imageUses)) return $this->imageUses;
$pages= array();
$this->usedWikis= array();
#print_r($this->wikis);
foreach (array_keys($this->wikis) as $l) {
$wiki=& $this->wikis[$l];
$db = $this->getDbConnection($wiki);
if ($this->imageInfo) {
$info= $this->loadImageInfo($wiki,$this->image);
if ($info) {
if ( $info->img_size != $this->imageInfo->img_size
|| $info->img_width != $this->imageInfo->img_width
|| $info->img_height != $this->imageInfo->img_height
|| $info->img_minor_mime != $this->imageInfo->img_minor_mime
|| $info->img_metadata != $this->imageInfo->img_metadata ) {
$this->trace(2,"image is shadowed locally on ".$wiki->domain.", skipping");
continue;
}
}
}
$this->trace(1,"looking for usage on ".$wiki->domain." wiki");
#print "findImageUses:W: $wiki ;";
#print "findImageUses:DB: ".$db." ;";
$img= $wiki->asDBKey($this->image);
$sql= "SELECT il_from, page_title, page_namespace
FROM ".$wiki->dbname.".imagelinks
JOIN ".$wiki->dbname.".page ON page_id = il_from
WHERE page_namespace = 0
AND il_to = " . $db->addQuotes( $img )."
LIMIT 16"; #16 should be enough for categoprization.
$this->sqlTrace($sql);
$res= $db->query( $sql, 'findImageUses' );
while ( $row = $db->fetchRow($res) ) {
unset($p);
$p= array(
'domain' => $wiki->domain,
'id' => $row['il_from'],
'title' => $row['page_title'],
'namespace' => $row['page_namespace']
);
$pages[]=& $p;
if (!isset($this->usedWikis[$wiki->domain])) $this->usedWikis[$wiki->domain]= array();
$this->usedWikis[$wiki->domain][]= $p;
$this->trace(3,"image ".$this->image." used on ".$wiki->domain.":".$row['page_title']);
}
$db->freeResult( $res );
if (sizeof($pages)>10) {
$this->trace(2,"found enough image uses, stopping search");
break;
}
}
$this->imageUses= $pages;
return $pages;
}
function randomImage() {
#print_r($this->wikis);
$l= array_rand($this->wikis,1);
$wiki=& $this->wikis[$l];
$db = $this->getDbConnection($wiki);
if (!$wiki) return NULL;
$sql= 'select img_name
from '.$wiki->dbname.'.image
join page use index(page_random) on page_title = img_name
where page_random > '.(rand()/getrandmax()).' order by page_random limit 1';
#print "W: $wiki ;";
#print "DB: ".$db." ;";
$this->sqlTrace($sql);
$res= $db->query( $sql, 'randomImage' );
if ( $row = $db->fetchRow($res) ) {
$this->image= $row['img_name'];
}
$db->freeResult( $res );
$this->mainWiki= $wiki;
return $this->image;
}
function randomUncategorizedCommonsImage() {
$db = $this->getDbConnection($this->commons);
extract( $db->tableNames( 'page', 'image', 'imagelinks', 'categorylinks' ) );
global $commonsLicenseCategories;
$ignoreCats= '';
foreach ($commonsLicenseCategories as $c) {
if ($ignoreCats) $ignoreCats.= ', ';
$ignoreCats.= $db->addQuotes($c);
}
$sql= 'SELECT I.page_title as title
FROM page AS I USE INDEX(page_random)
LEFT JOIN categorylinks AS L ON (I.page_id = L.cl_from AND L.cl_to NOT IN ('.$ignoreCats.'))
LEFT JOIN ( imagelinks AS P JOIN page as A ON A.page_id = P.il_from AND A.page_namespace = 0 ) ON I.page_title = P.il_to
WHERE I.page_namespace = '.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL
AND I.page_random > '.(rand()/getrandmax()).' ORDER BY I.page_random LIMIT 1
';
/*
$sql= 'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description
FROM '.$page.' AS I USE INDEX(page_random)
LEFT JOIN '.$categorylinks.' AS L ON I.page_id = L.cl_from AND L.cl_to NOT IN ('.$ignoreCats.')
LEFT JOIN '.$imagelinks.' AS P ON I.page_title = P.il_to AND I.page_namespace = 0
INNER JOIN '.$image.' AS G ON I.page_title = G.img_name
WHERE I.page_namespace = '.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL
AND I.page_random > '.(rand()/getrandmax()).' ORDER BY I.page_random LIMIT 1';
*/
$this->sqlTrace($sql);
$res= $db->query( $sql, 'randomImage' );
if ( $row = $db->fetchRow($res) ) {
$this->image= $row['title'];
}
$db->freeResult( $res );
$this->mainWiki= $this->commons;
return $this->image;
}
function processPage( &$wiki, $title, $ns, &$gals, &$cats, $depth ) {
$info= NULL;
$k= $wiki->domain.":$ns:$title";
list($d, $r)= @$this->processed[$k];
if ($d>=$depth) {
//$this->trace(1,"SKIPPING processing ".$wiki->domain.": ($ns) $title (depth: $depth): CACHED: ".$this->stringValue($r));
return $r;
}
$this->processed[$k]= array($depth, true); //FIXME: may be misleading (self-fulfilling) if loops are encountered
$this->trace(1,"processing ".$wiki->domain.": ($ns) $title (depth: $depth)");
$info= $this->loadPageInfo($wiki, $title, $ns);
if (!$info) {
$this->processed[$k]= array($depth, false);
return false;
}
if ( $wiki->domain != 'en' && $wiki->domain != 'en.wikipedia.org' ) {
if ( isset($info['english']) && !is_null($info['english']) && $this->processPage( $this->enwiki, $info['english'], $ns, $gals, $cats, 1 ) ) {
if ( ! @$info['commons'] ) return true; #note: keep going for direct commons links
}
}
$titles= array( $title );
if ( @$info['commons'] ) {
$this->trace(2,"found commons links",$info['commons']);
$titles= array_merge($titles,$info['commons']);
}
$found= false;
foreach ($titles as $ttl) {
if ( $t= $this->getCommonsTitle( $ttl, NS_MAIN ) ) {
$gals[]= $t;
$found= true;
}
if ( $t= $this->getCommonsTitle( $ttl, NS_CATEGORY ) ) {
$cats[]= $t;
$this->processed[$k]= array($depth, true);
$found= true;
}
}
if ($found) {
$this->processed[$k]= array($depth, true);
return true;
}
if ( $depth <= 1 ) {
$this->processed[$k]= array($depth, false);
return false;
}
if ( @$info['categories'] ) {
foreach ( $info['categories'] as $c ) {
if ( $this->processPage( $wiki, $c, NS_CATEGORY, $gals, $cats, $depth-1 ) )
$found= true;
}
}
if ($found) {
$this->processed[$k]= array($depth, true);
return true;
}
#if nothing was found, deep-scan english version (FIXME: root level only?!)
if ( !$found && isset($info['english']) && !is_null($info['english']) && $wiki->domain != 'en.wikipedia.org') {
if ( $this->processPage( $this->enwiki, $info['english'], $ns, $gals, $cats, $depth ) ) {
$this->processed[$k]= array($depth, true);
return true;
}
}
$this->processed[$k]= array($depth, $found);
return $found;
}
function getCommonsTitle( $title, $ns ) {
return $this->getPageTitle( $this->commons, $title, $ns );
}
function getPageTitle( &$wiki, $title, $ns ) {
$title= $this->commons->asDBKey($title); #FIXME: use which connection? ucfirst?
$k= "{$wiki->dbname}:$ns:$title";
if (array_key_exists($k, $this->pageTitle)) return $this->pageTitle[$k];
$db = $this->getDbConnection($wiki);
$tries= 3;
while ($tries) {
$sql= "SELECT page_id, page_title, page_is_redirect
FROM ".$wiki->dbname.".page
WHERE page_namespace = $ns
AND page_title = " . $db->addQuotes( $this->commons->asDBKey($title) );
$this->sqlTrace($sql);
$res= $db->query( $sql, 'getPageTitle' );
if ( ! ($row = $db->fetchRow($res)) ) {
$this->trace(3,"NOT found on ".$wiki->domain.": ($ns) $title");
$title= NULL;
$tries= 0;
}
else if (!$row['page_is_redirect']) {
#TODO: category-redirects: {{Categoryredirect|xxx}}, {{seecat|xxx}}, etc
if ( $ns == NS_CATEGORY ) {
$info= $this->loadPageInfo($wiki, $title, $ns);
#TODO: use wiki-specific cat-redirect pattern
$match= array();
if (preg_match(CATEGORY_REDIRECT_PATTERN,$info['text'],$match)) {
$tries-= 1;
if (!$tries) $title= NULL;
else {
$t= $match[2];
$this->trace(3,"FOUND CATEGORY REDIRECT on ".$wiki->domain.": ($ns) $title -> $t");
$title= $t;
}
}
else {
$this->trace(3,"FOUND on ".$wiki->domain.": ($ns) $title");
$tries= 0;
}
}
else {
$this->trace(3,"FOUND on ".$wiki->domain.": ($ns) $title");
$tries= 0;
}
}
else {
$tries-= 1;
if (!$tries) $title= NULL;
else {
$info= $this->loadPageInfo($wiki, $title, $ns);
if (!$info) {
$this->trace(3,"found BAD on ".$wiki->domain.": ($ns) $title");
$title= NULL;
$tries= 0;
}
else {
$match= array();
if (!preg_match(REDIRECT_PATTERN,$info['text'],$match)) {
$this->trace(3,"found BAD redirect on ".$wiki->domain.": ($ns) $title; {$info['text']}");
$title= NULL;
$tries= 0;
}
else {
$t= $match[1];
$this->trace(3,"FOUND REDIRECT on ".$wiki->domain.": ($ns) $title -> $t");
$title= $t;
}
}
}
}
$db->freeResult( $res );
}
$this->pageTitle[$k]= $title;
#$this->trace(3,"TITLE on commons: ($ns) $title");
return $title;
}
function loadImageInfo( &$wiki, $title ) {
$title= $this->commons->asDBKey($title);
$db = $this->getDbConnection($wiki);
$this->trace(4,"loading image info for $title from [".$wiki->domain."]...");
$sql= "SELECT *
FROM ".$wiki->dbname.".image
WHERE img_name = " . $db->addQuotes( $title );
$res= $db->query($sql);
if ( ! $res ) {
$this->trace(1,"failed to load image info for $title from [".$wiki->domain."]", $sql);
$info= false;
}
if ( ! ($info = $db->fetchObject($res)) ) {
$this->trace(4,"no image info for $title from [".$wiki->domain."]");
#print "*** $sql ***";
$info= false;
}
$db->freeResult($res);
return $info;
}
function loadPageInfo( &$wiki, $title, $ns ) {
$k= $wiki->domain.":$ns:$title";
if (array_key_exists($k, $this->pageInfo)) return $this->pageInfo[$k];
$fulltitle= $ns==0 ? $title : MWNamespace::getCanonicalName( $ns ) . ':' . $title; #fixme: ucfirst!
$this->trace(4,"loading $fulltitle from [".$wiki->domain."]...");
$db = $this->getDbConnection($wiki);
#FIXME: ugly hack...
global $wgLoadBalancer;
$wgLoadBalancer= new PseudoLoadBalancer( $db );
$info= $wiki->loadInfoFromDB( $title, $ns ); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if ( !$info ) {
$this->trace(4,"failed to load $fulltitle from [".$wiki->domain."]");
$this->pageInfo[$k]= false;
return false;
}
$info['title']= $title;
$info['namespace']= $ns;
$info['fulltitle']= $fulltitle;
if ( $wiki->domain != 'en.wikipedia.org') {
$info['english']= $this->extractTranslation($info['text'], 'en');
}
#$this->trace(4,"loaded $fulltitle from [".$wiki->domain."]");
$info['categories']= $this->getCategories( $wiki, $title, $ns );
$info['commons']= $this->getCommonsLinks( $wiki, $info['text'] );
if (@$info['english']) $this->trace(5,"english",$info['english']);
if (@$info['commons']) $this->trace(5,"commons",$info['commons']);
if (@$info['categories']) $this->trace(5,"categories",$info['categories']);
$this->pageInfo[$k]= $info;
return $info;
}
function extractTranslation( $text, $lang ) {
$match= array();
if (!preg_match('/\[\['.$lang.':([^\|\:\]]+:)*([^\]\|]+)(\|[^\]]*)?\]\]/smi',$text,$match)) {
return NULL;
}
else {
#$this->trace(4,"TRANSLATION: matched ".@$match[0]." -> ".$match[1]." || ".$match[2]." || ".@$match[3]);
return $match[2];
}
}
function getCommonsLinks( &$wiki, $text ) {
$match= array();
$num= preg_match_all(COMMONS_LINK_PATTERN,$text,$match,PREG_PATTERN_ORDER);
if (!$num) return NULL;
$links= array();
for ($i=0; $i<$num; $i+=1) {
if ($match[2][$i]) $links[]= $match[2][$i];
else {
#NOTE: try first and second template-arg! (de and en use different order for {{Commons2}})
if ($match[6][$i]) $links[]= $match[6][$i];
if ($match[8][$i]) $links[]= $match[8][$i];
}
}
return $links;
}
function getCategories( &$wiki, $title, $ns ) {
$db = $this->getDbConnection($wiki);
$sql= "SELECT cl_to
FROM ".$wiki->dbname.".categorylinks
JOIN ".$wiki->dbname.".page ON page_id = cl_from
WHERE page_namespace = $ns
AND page_title = " . $db->addQuotes( $title );
$this->sqlTrace($sql);
$res= $db->query( $sql, 'getCategories' );
$cats= array();
while ( $row = $db->fetchRow($res) ) {
$cats[]= $row[0];
}
$db->freeResult( $res );
#$this->trace(5,"categories for ($ns) $title from [".$wiki->domain."]:",$cats);
return $cats;
}
function extractKeywords( $text, $title = false ) {
$kw= array();
if ($title) {
$text= preg_replace('/\.[\w\d]+$/si','',$text);
}
else if (strpos($text,'[')!==false && isset($this)) {
$links= $this->commons->extractLinks( $text );
foreach ($links as $lnk) {
if (sizeof($kw)>=10) break;
$s= $lnk['link'];
if (strpos($s,':')!==false) continue;
$kw[]= str_replace(' ', '_', $s);
}
}
if ( sizeof($kw) < 10 ) {
$text= str_replace(array('_','(',')','.',';',',','-','/','"','*',':','#',"'",'='),' ',$text);
$text= stripMarkup($text);
$text= preg_replace('!\[\[.*?\]\]|\{\{.*?\}\}|\[\w+://[^\]]+\]|\w+://[^\s]+!smi','',$text);
$words= preg_split('/\s+/smi',$text);
foreach ($words as $w) {
if (sizeof($kw)>=10) break;
if (strlen($w)<4) continue;
$w= preg_replace('/^[,;.:!\/$%"()?\']|[,;.:!\/$%"()?\']$/smi','',$w);
$w= trim($w);
if (strlen($w)<4) continue;
if (preg_match('/^[\d.:,;\/\']+$/',$w)) continue;
if (preg_match('!^(GFDL|GNU-FDL|GPL|\w+://[^\w]+)$!i',$w)) continue;
$kw[]= $w;
}
}
$kw= array_unique($kw);
return $kw;
}
function prepareOutput() {
if ($this->image && $this->mainWiki) {
$this->imageInfo= $this->loadImageInfo($this->mainWiki,$this->image);
if (!$this->imageInfo) {
$this->error($this->msg('image_not_found_error_1',$this->mainWiki->domain));
return false;
}
}
return true;
}
function generateTxtOutput() {
if (!$this->prepareOutput()) return false;
$this->verbosity= -100;
$res= $this->findCategories();
$cats= @$res['categories'];
$gals= @$res['galleries'];
print "#COMMONSENSE\n";
print "projects: ".$this->projects."\n";
print "image: ".$this->image."\n";
print "\n";
print "#USAGE (".sizeof($this->usedWikis).")\n";
$this->printUsageTxt($this->usedWikis);
print "\n";
print "#KEYWORDS (".($this->keywordWikis ? sizeof($this->keywordWikis) : 0).")\n";
if ($this->keywordWikis) $this->printUsageTxt($this->keywordWikis);
print "\n";
print "#CATEGORIES (".sizeof($cats).")\n";
foreach ($cats as $c) {
print $c."\n";
}
print "\n";
print "#GALLERIES (".sizeof($gals).")\n";
foreach ($gals as $g) {
print $g."\n";
}
print "\n";
print "#EOF\n";
}
function printUsageTxt( &$usage ) {
if (!$usage) return;
foreach ($usage as $domain => $pages) {
#if ($domain=='commons.wikimedia.org') $wiki=& $this->commons;
#else $wiki=& $this->wikis[$domain];
print "$domain: ";
foreach ($pages as $page) {
$t= $page['title'];
if ($page['namespace']) $t= MWNamespace::getCanonicalName( $page['namespace'] ) . ':' . $t;
print "$t ";
}
print "\n";
}
}
function printUsageHTML( &$usage, $linkImage = NULL ) {
if (!$usage) return;
foreach ($usage as $domain => $pages) {
if ($domain=='commons.wikimedia.org') $wiki=& $this->commons;
else $wiki=& $this->wikis[$domain];
if ( $linkImage ) {
$lnk= $wiki->baseURL . "?title=Image:" . urlencode( $this->commons->asDBKey($linkImage) );
print "<b><a href='$lnk'>".escapeHtml($domain)."</a>:</b> ";
}
else {
print "<b>".escapeHtml($domain).":</b> ";
}
foreach ($pages as $page) {
$t= $page['title'];
if ($page['namespace']) $t= MWNamespace::getCanonicalName( $page['namespace'] ) . ':' . $t;
$lnk= $wiki->baseURL . "?title=" . urlencode( $t );
print " <a href='$lnk'>".escapeHtml($t)."</a>, ";
}
print "<br/>\n";
}
}
function generateHtmlOutput() {
if (!$this->prepareOutput()) return false;
$title= "Image:".$this->image;
if ($this->mainWiki) {
print "\n\t\t<div class='thumb'>";
print $this->mainWiki->getThumbnailHTML($this->image, 120);
print "</div>\n";
}
/*if ($this->mainWiki && $this->imageInfo && preg_match('/\.(jpe?g|gif|png|svg)$/i',$this->image)) {
$thumbwidth= 180;
#FIXME: ugly hack: thumb.php refuses to give full size images!
if ($this->imageInfo->img_width<$thumbwidth) $thumbwidth= $this->imageInfo->img_width -1;
$u= "http://{$this->mainWiki->domain}/w/thumb.php?f=".urlencode($this->image)."&w=$thumbwidth";
if ( !preg_match('/\.(jpe?g|gif|png)$/i',$this->image) ) {
$u.= "&r=1";
}
$lnk= $this->mainWiki->baseURL . "?title=" . urlencode( $title );
print "\n\t\t<div class='thumb'>";
print "<a href='$lnk'><img src='$u' border='0' alt='".escapeHtml($title)."'/></a>";
print "</div>\n";
}*/
$tkw= array();
$tkw+= $this->extractKeywords($this->image,true);
if ($this->imageInfo && $this->mainWiki) {
$info= $this->loadPageInfo( $this->mainWiki, $this->image, NS_IMAGE );
$text= $info ? $info['text'] : false;
if ($text !== false) {
$text= escapeHtml( $text );
$text= str_replace("\r\n",'<br/>',$text);
$text= str_replace("\r",'<br/>',$text);
$text= str_replace("\n",'<br/>',$text);
$lnk= $this->mainWiki->baseURL . "?title=" . urlencode( $title );
print "<h4>".$this->msg('image_description_2',$lnk,escapeHtml($title))."</h4>\n";
print "<div class='wikitext'>$text</div>\n";
if ($this->mainWiki->domain=='commons.wikimedia.org') {
print "<p><b>[<i><a href='$lnk&action=edit'>".$this->msg('edit_description')."</a></i>]</b></p>\n";
}
if ($text) {
$tkw+= $this->extractKeywords($text,false);
}
}
else {
$this->error($this->msg('image_load_error_2',$title,$this->mainWiki->domain));
}
}
print "\n<h4>".$this->msg('searching_for_categories')."</h4>\n";
print "\n<div style='font-size:80%; padding:0; padding-left:3ex;'>\n";
$res= $this->findCategories();
print "\n</div>\n";
$cats= @$res['categories'];
$gals= @$res['galleries'];
if ( !$this->usedWikis && !$this->keywordWikis) {
$this->error($this->msg('no_matches_error'));
}
else {
if ( $this->usedWikis ) {
print "\n<p>".$this->msg('image_used_on_pages_1',escapeHtml($title))."<br/>";
$this->printUsageHTML( $this->usedWikis, $this->image);
print "</p>\n";
}
else if ($this->image) {
?>
<p style='font-weight:bold;'><?= $this->msg('image_not_used')?></p>
<?
}
if ( $this->keywordWikis ) {
print "\n<p>".$this->msg('keywords_match_pages')."<br/>";
$this->printUsageHTML( $this->keywordWikis, NULL);
print "</p>\n";
}
else if ( $this->keywords ) {
?>
<p style='font-weight:bold;'><?=$this->msg('keywords_not_found')?></p>
<?
}
}
if ($tkw) {
global $projrq, $customlang, $scanwiki, $mode; #ugly
$u= $_SERVER['PHP_SELF']."?i=".urlencode($this->image)."&p=".urlencode($projrq)."&cl=".urlencode($customlang)."&u=".urlencode($this->messages->language)."&v=".urlencode($this->verbosity)."&w=".urlencode($scanwiki)."&m=".urlencode($mode)."&";
if ($this->keywords) $kw= array_unique( array_merge( $this->keywords, $tkw ) );
else $kw= $tkw;
$u.= "kw=".urlencode( implode(', ',$kw) );
print "<p><i>".$this->msg('use_keywords_from_description_2',$u,escapeHtml(implode(', ',$kw)))."</i></p>\n";
}
if ( $this->usedWikis || $this->keywordWikis ) {
if ( !$cats && !$gals ) {
?>
<p><?=$this->error($this->msg('nothing_found'))?></p>
<?
}
else {
print "\n<div class='box' style='clear:both; margin-top:1ex;'>";
if ($cats) {
?>
<h3><?=$this->msg('suggested_categories')?></h3>
<div style='display:table-row;'>
<div style='display:table-cell; padding-right:1em; text-align:left; width:60%'>
<ul style='vertical-align:top; text-align:left; margin:0;'>
<?
foreach ($cats as $c) {
print $this->commons->makeExpandableCategoryItemHTML($c);
}
?>
</ul>
</div>
<div style='display:table-cell; vertical-align:top; width:40%;' class='wikitext'>
<?
foreach ($cats as $c) {
$c= str_replace('_',' ',$c);
print "[[Category:".escapeHtml($c)."]]<br/>";
}
?>
</div>
</div>
<p style="font-size:80%"> <?= $this->msg('verify_cats_text') ?>
</p>
<?
}
if ($gals) {
?>
<h3><?= $this->msg('suggested_galleries') ?></h3>
<ul>
<?
foreach ($gals as $g) {
print "<li><a href='http://commons.wikimedia.org/wiki/".urlencode(str_replace(' ','_',$g))."'>".escapeHtml($g)."</a></li>";
}
?>
</ul>
<?
}
print "\n</div>";
}
print "\n<a name='result'></a>";
global $wsgBrowser;
if ($wsgBrowser && !$wsgBrowser['opera'] && !$wsgBrowser['khtml']) {
print "\n<script type='text/javascript'>window.location.hash='#result'</script>";
}
}
}
}
if (defined('WS_TEST_COMMON_SENSE')) {
$txt= implode(' ',$args);
$kw= CommonSensePage::extractKeywords($txt);
print_r($kw);
exit;
}
#$wsgLogLevel= LL_VERBOSE;
$knownLanguages= array('ar', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'fr', 'it', 'ja', 'km', 'nl', 'pl', 'pt', 'ru', 'sk', 'th', 'vi', 'wa', 'wo', 'zh', 'zh-hans', 'zh-hant');
$wsgCommonSenseText=& WikiSenseLocalizer::initialize('CommonSense', $knownLanguages, $wgRequest->getVal('go-u'), 'u', 'ws-interface-lang');
$img= $wgRequest->getVal("i");
$keywords= $wgRequest->getVal("kw");
$lang= $wgRequest->getVal("l");
$projrq= $wgRequest->getVal("p","_20");
$scanwiki= $wgRequest->getVal("w");
$customlang= $wgRequest->getVal("cl");
$verb= $wgRequest->getVal("v",0);
$raw= $wgRequest->getVal("r",0);
$keepRedundant= $wgRequest->getVal("k",0);
$errors= array();
if ( !is_null($projrq) ) $projrq= trim($projrq);
if ( empty($projrq) ) $projrq= NULL;
#if ($wgRequest->getVal('go-move')) $mode= 'move';
#if ($wgRequest->getVal('go-clean')) $mode= 'clean';
#if (!$projrq) $mode= NULL;
if ( !is_null($img) ) $img= trim($img);
if ( empty($img) ) $img= NULL;
if ( $img ) {
$match= array();
if (preg_match('/^\w+:(.*)$/',$img,$match)) {
$img= $match[1];
}
}
$mode= NULL;
if ($wgRequest->getVal("random") || $wgRequest->getVal("go-move")) {
$mode= 'move';
}
if ($wgRequest->getVal("uncategorized") || $wgRequest->getVal("go-clean")) {
$mode= 'clean';
}
if (!$mode) {
$mode= $wgRequest->getVal("m");
}
if (!$mode && $lang) {
$mode= 'move';
}
if (!$mode && !$scanwiki) {
$scanwiki= WikiSenseLocalizer::detectUserLanguage( $wsgLanguages, '', $wsgCommonSenseText->language );
}
if (!$lang) {
if ($mode=='clean') {
$lang= $projrq;
$lang= strtolower($lang);
$m= array();
$fam= 'wikipedia';
if ($lang == "major") $lang= '_15';
else if ($lang == "wps") $lang= '_1000000';
else if ($lang == "all") {
$lang= '_1000000';
$fam= NULL;
}
if (preg_match('/^_(\d+)/',$lang,$m)) {
$n= $m[1];
$w= getLargestWikis($n,$fam);
$lang= implode(', ',array_keys($w));
}
if ($customlang) {
if (!$lang) $lang= $customlang;
else $lang.= ',' . $customlang;
}
}
if ($mode=='move') {
$lang= $scanwiki;
}
}
$page= NULL;
if ( $lang) {
if ( $wgRequest->getVal("random") ) {
$keywords= NULL;
$page= new CommonSensePage( $lang, NULL );
$img= $page->randomImage();
$page->stripRedundant= !$keepRedundant;
}
else if ( $wgRequest->getVal("uncategorized") ) {
$keywords= NULL;
$page= new CommonSensePage( $lang, NULL );
$img= $page->randomUncategorizedCommonsImage();
$page->stripRedundant= !$keepRedundant;
}
else if ($img || $keywords) {
$page= new CommonSensePage( $lang, $img, $keywords );
$page->stripRedundant= !$keepRedundant;
}
}
if ( $page ) {
if ($mode=='clean') {
$page->mainWiki= $page->commons;
}
#$lang= implode(', ',array_keys($page->wikis));
if ($wgRequest->getVal("debug") ) {
$page->sqlDebug= true;
}
if ($page->errors ) {
$errors= $page->errors;
}
if (!$page->wikis ) {
$page->close();
$page= NULL;
$projrq= NULL;
$lang= NULL;
#$mode= NULL;
}
}
if ( $page && $raw && ($img || $keywords)) {
header("Content-Type: text/plain; charset=UTF-8");
$page->generateTxtOutput();
$page->close();
exit();
}
header("Content-Type: text/html; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='<?=$wsgCommonSenseText->language?>' lang='<?=$wsgCommonSenseText->language?>'>
<head>
<title>CommonSense</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<?
if ($img || $keywords) print '<meta name="robots" content="noindex, nofollow"/>';
else print '<meta name="robots" content="nofollow"/>';
?>
<link rel="stylesheet" href="wikisense.css" type="text/css">
<style type='text/css'>
body { font-family: sans-serif; font-size:14px; }
.error { font-weight:bold; color:red; }
div.term { border:1px solid #AAAAAA; background-color: #F8F8FF; margin:1ex; }
.term p { margin-left: 1ex; margin-right: 1ex; }
.section { border:1px solid #AAAAAA; border-width:0 0 1px 0; background-color: #F0F0FF; padding:1ex; }
h3.section { margin:0; }
.wikitext { margin-left:2.5ex; padding:0.7ex;
font-family:monospace;
background-color:#F0F0F0;
border:1px dashed gray; }
div.thumb {
float:right;
margin: 1ex 0 1ex 1ex;
padding: 1ex;
background-color:#EEEEEE;
border:1px solid #AAAAAA;
}
.box {
border:1px solid #AAAAAA;
background-color: #EEEEEE;
padding:0 1ex 1ex 1ex;
margin:0;
margin-bottom:1ex;
}
.box h3 { margin-top:0; padding-top:0; }
</style>
<script type='text/javascript' src="Bonsai.js"></script>
<script type='text/javascript'>
function submitOnEnter(event, button) {
if (event.keyCode != 13) return true;
if (!button) return false;
button= document.getElementById(button);
if (button) button.click();
return false;
}
</script>
</head>
<body>
<? #wsfHackingInProgress() ?>
<? #print "LANG: $lang; MODE: $mode; PAGE: $page; IMG: $img; KW: $keywords;"; ?>
<? #if ($page) print_r($page->mainWiki); ?>
<? wsfHeader(); ?>
<div id='content' class='centerbox'>
<form method="get" action="CommonSense.php">
<div style='float:right; clear:right;'>
<?
$lag= wsfGetReplagHTML();
if ($lag) print "<p class='replag'>$lag</p>";
?>
<? $wsgCommonSenseText->printLanguageSelector($knownLanguages); ?>
<input type="submit" name="go-u" value="<?= $wsgCommonSenseText->msg('set_language') ?>"/>
<br/><? $wsgCommonSenseText->printTranslationLink('CommonSense') ?>
</div>
<h1>CommonSense</h1>
<? wsfSubtitle('CommonSense'); ?>
<p><?= $wsgCommonSenseText->msg('tag_line') ?> </p>
<!-- <p style="font-size:90%"> <?= $wsgCommonSenseText->msg('intro_text') ?> </p> -->
<?
if ( $errors ) {
foreach ( $errors as $e ) {
CommonSensePage::error($e);
}
}
?>
<?
if ($lang && !$img && !$keywords) {
CommonSensePage::error($wsgCommonSenseText->msg('missing_image_or_keyords_error'));
}
?>
<?
if ($mode && !$lang) {
CommonSensePage::error($wsgCommonSenseText->msg('missing_custom_project_error'));
}
?>
<div class='box'>
<table>
<tr>
<td valign='top'> </td>
<td valign='top'>
<small><?=$wsgCommonSenseText->msg('top_help')?></small>
</td>
</tr>
<tr>
<td style='padding:0.5ex; white-space:nowrap;' valign='top'><?= $wsgCommonSenseText->msg('image_label') ?></td>
<td style='padding:0.5ex;' valign='top'><input type="text" name="i" style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;" value="<?= escapeHtml($img) ?>" onkeypress="return submitOnEnter(event, null);"/></td>
<td style='padding:0.5ex;' valign='top' rowspan="2"><small><?=$wsgCommonSenseText->msg('bot_output_label')?>: <input type="checkbox" name="r" onkeypress="return submitOnEnter(event,null);"/></small></td>
</tr>
<tr>
<td style='padding:0.5ex; white-space:nowrap;' valign='top'><?= $wsgCommonSenseText->msg('keywords_label') ?> </td>
<td style='padding:0.5ex;' valign='top'><textarea name="kw" rows="3" style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;"><?=escapeHtml($keywords)?></textarea></td>
</tr>
<tr>
<td colspan="2" valign='top'>
<h4 style="margin:0; padding:0; padding-top:0.5ex; font-size:120%;"><?=$wsgCommonSenseText->msg('image_on_commons_header')?><br/></h4>
<?#=$wsgCommonSenseText->msg('project_selector_header')?>
</td>
</tr>
<tr>
<td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('project_selector_label')?></td>
<td style='padding:0.5ex;' valign='top'>
<? printRadioButton('p','_20',$projrq) ?> 20
<? printRadioButton('p','_80',$projrq) ?> 80
<? printRadioButton('p','wps',$projrq) ?> <?=$wsgCommonSenseText->msg('all_wikipedias')?>
<!-- <? printRadioButton('p','all',$projrq) ?> <?=$wsgCommonSenseText->msg('all_projects')?> -->
</td>
<td style='padding:0.5ex;' align='right' valign='top'><input type="submit" id="go-clean" name="go-clean" value="<?=$wsgCommonSenseText->msg('find_categories')?>"/></td>
</tr>
<tr>
<td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('custom_projects_label')?></td>
<td valign='top'>
<input type="text" name="cl" style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;" value="<?= escapeHtml($customlang) ?>" onkeypress="return submitOnEnter(event, 'go-clean');"/>
<br/><small><?=$wsgCommonSenseText->msg('project_field_help')?></small>
<br/><? printRadioButton('p','',$projrq) ?> <?=$wsgCommonSenseText->msg('custom_projects_only')?>
</td>
<td style='padding:0.5ex;' align='right' valign='top'><input type="submit" name="uncategorized" value="<?=$wsgCommonSenseText->msg('random_commons_orphan')?>"/> </td>
</tr>
<tr>
<td colspan="2" valign='top'>
<h4 style="margin:0; padding:0; padding-top:0.5ex; font-size:120%;"><?=$wsgCommonSenseText->msg('image_in_wiki_header')?></h4>
</td>
</tr>
<tr>
<td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('scan_wiki_label')?></td>
<td style='padding:0.5ex;' valign='top'>
<input name="w" style="width: 16ex; font-family: verdana,helvetica,arial,sans-serif; font-size: 80%;" value="<?= escapeHtml($scanwiki) ?>" type="text" onkeypress="return submitOnEnter(event, 'go-move');"/>
<br/><small><?=$wsgCommonSenseText->msg('single_wiki_help')?></small>
</td>
<td style='padding:0.5ex;' align='right' valign='top'>
<input type="submit" id="go-move" name="go-move" value="<?=$wsgCommonSenseText->msg('find_categories')?>"/>
<div style='height:1ex; font-size:50%;'> <div/>
<input type="submit" id="random" name="random" value="<?=$wsgCommonSenseText->msg('random_wiki_image')?>"/>
</td>
</tr>
</table>
<input type="hidden" name="v" value="<?= escapeHtml($verb) ?>"/>
</div>
<?
if ( $page && ($img || $keywords)) {
#if ($mode=='clean' && (!$page->mainWiki || $page->mainWiki->domain!='commons.wikimedia.org')) {
# $page->mainWiki= $page->commons;
#}
$page->verbosity= $verb;
$page->generateHtmlOutput();
}
?>
</form>
</div>
<? wsfFooter(false); ?>
</body>
</html>
<?
if ($page) $page->close();
wfDebug( "Request ended normally\n" );
/*
[22:37] <Multichil> Duesentrieb : You around? Feel like trying a filter function?
[22:38] <Duesentrieb> Multichil: can you post it somewhere? I'll look at it in a bit.
[22:40] <Multichil> Duesentrieb /home/multichill/public_html/inc/filtercats_inc.php
[22:41] <Multichil> Just pass an array of categories and it will return two arrays. One with the new categories and one with the categories which were filtered out.
[22:44] <Duesentrieb> Multichil: thanks. i'm kind of tired, dunno if i'll look at it today... otherwise i'll do it tomorrow
[22:45] <Multichil> No rush. You should just be able to include the file and use the function. See /home/multichill/public_html/filtercats.php line 45-48 for an example.
*/
?>
CommonSense.php
application/x-php, 63368 bytes (load raw)

