root > WikiSense-trunk > web > CategoryIntersect.php

CategoryIntersect.php

application/x-php, 41451 bytes (load raw)
<?php

/*
CatScan searches MediaWiki categories.
Copyright (C) 2005, Daniel Kinzler, brightbyte.de

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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/


define("WS_WEB",true);
require_once( "common/WebInit.php" );

require_once( "WikiAccess.php" );
require_once( "WikiSelector.php" );
require_once( "WikiSenseLocalizer.php" );
require_once( "QCache.php" );

function printWikiLinks($titles, $ns) {
        global $wiki;

        if (!is_array($titles)) {
                $titles= explode('|',$titles);
        }

        $first = true;
        foreach ($titles as $ttl) {
                if ($first) $first = false;
                else print ", ";
                $n = $wiki->asUrlName($ns, $ttl);
                print "[[:$n|$ttl]]";
        }
}

function printLinks($titles, $ns) {
  global $wiki, $terse, $wgCanonicalNamespaceNames;
 
  if (!is_array($titles)) {
      $titles= explode('|',$titles);
  }
 
  sort($titles);
 
  $s= '';
  foreach ($titles as $c) {
      if (!$c) continue;
     
      if ($s) $s.= ', ';
     
      $label= escapeHtml(str_replace('_',' ',$c));
     
      if ($wiki && $wiki->baseURL) {
        $t= getPrefixedTitle($c, $ns);
       
        $wikiLink= $wiki->baseURL . '?title=' . urlencode($t);
      }
      else $wikiLink= NULL;
     
      if ($wikiLink) $s.= "<a href='$wikiLink'>$label</a>";
      else $s.= $label;
  }
 
  print $s;
}

function getPrefixedTitle($title, $ns) {
  global $wiki;
  $t= $title;
 
  if ($ns) {
      $n= $wiki->getNsText($ns);
      if (!$n) $n= $ns;
         
      $t= $n . ':' . $t;
  }
 
  return $t;
}

$thumbCol= 0;
$maxThumbCol= 4;

function printImageHTML($page, $mode = NULL) {
  global $wiki, $commons, $thumbCol, $maxThumbCol;

  if ($thumbCol==0) print "\n<tr>\n";

  $wikiLink= NULL;
 
  $t= getPrefixedTitle($page->page_title, $page->page_namespace);
 
  $label= escapeHtml(str_replace('_',' ',$page->page_title));
 
  if ($page->on_commons) $w=& $commons;
  else $w=& $wiki;
 
  if ($w && $w->baseURL) {
    $wikiLink= $w->baseURL . '?title=' . urlencode($t);
  }
 
  ?>
    <td align='center' class='cell'>
       <div class='thumb' style='margin-left:auto; margin-right:auto; text-align:center;'>
                <?= $w->getThumbnailHTML($page)?>
       </div>
       <div class='thumblabel'>
            <small><a href='<?=$wikiLink?>'><?=$label?></a>
            <? if ($page->on_commons) print "(commons)"; ?>
            </small>
       </div>
      <? if (@$page->used_in): ?>
       <p class='tags' style='text-align:left;'>
        <b>Used in</b>: <? printLinks($page->used_in,NS_MAIN); ?>
       </p>
      <? endif; ?>
      <? if (@$page->cats): ?>
       <p class='cats' style='text-align:left;'>
        <b>Categories</b>: <? printLinks($page->cats,NS_CATEGORY); ?>
       </p>
      <? endif; ?>
       
    </td>
  <?
 
  $thumbCol+= 1;

  if ($thumbCol>=$maxThumbCol) {
      print "\n</tr>\n";
      $thumbCol= 0;
  }

}

function printArticleHTML($page, $mode = NULL) {
  global $wiki, $terse, $wsgCatScanText;
 
  $wikiLink= NULL;
 
  $t= getPrefixedTitle($page->page_title, $page->page_namespace);
 
  $label= escapeHtml(str_replace('_',' ',$t));
 
  if ($wiki && $wiki->baseURL) {
    $wikiLink= $wiki->baseURL . '?title=' . urlencode($t);
  }
 
  $n= NULL;
 
  $class= 'dummy';
  if ($mode == 'al' && @$page->tags) $class= 'highlite';
  ?>
  <tr class='leaf'>
    <td align='right'>
      <? if (@$page->cats): ?>
        <span class='cats'>
        <? printLinks($page->cats,NS_CATEGORY); ?>
        </span>
      <? endif; ?>
    </td>
   
    <td class='label'>
      <span class="<?= $class ?>">
        <a href='<?=$wikiLink?>'><?=$label?></a>
       
        <? if (@$page->page_restrictions && preg_match('/edit=(\w+)/',$page->page_restrictions,$m)): ?>
        <span class='restrictions restrictions_edit_<?= $m[1] ?>'>
          (<?= $wsgCatScanText->msg('restrictions_edit_'.$m[1]) ?>)
        </span>
        <? endif; ?>
       
        <? if (@$page->page_len): ?>
        <span class='tags'>
          (<?= $page->page_len ?> bytes)
        </span>
        <? endif; ?>
       
        <? if (@$page->page_len): ?>
        <span class='tags'>
          (<?= $page->page_len ?> bytes)
        </span>
        <? endif; ?>
       
        <? if (@$page->links): ?>
        <span class='tags'>
          (<?= $page->links ?> links)
        </span>
        <? endif; ?>
       
        <?
        if ($mode=='rc') {
            ?>
            <span class='log'>
              <?
                  print wfTimestamp(TS_DB,$page->rc_timestamp);
                     
                  print ', ';
                  print '<b>';
                  printLinks($page->rc_user_text, NS_USER );
                  print '</b>';
                   
                  print ' ';
                  print '(';
                 
                  if ($page->rc_type==1) print '<b>new</b>';
                  else if ($page->rc_type==2) print '<b>moved</b>';
                  else if ($page->rc_type==3) /*log*/ ;
                  else {
                      $lnk= $wikiLink.= '&amp;diff=prev&amp;oldid='.$page->rc_this_oldid;
                      print "<a href='$lnk'>diff</a>";
                  }
                 
                  print ', ';
                 
                  $lnk= $wikiLink.= '&amp;action=history';
                  print "<a href='$lnk'>versions</a>";
                     
                  print ')';
                 
                  if ($page->rc_comment) {
                      print ': ';
                      print '<i>';
                      print escapeHtml($page->rc_comment);
                      print '</i>';
                  }
                 
                  if ($page->rc_minor) {
                      print ' (<b>K</b>)';
                  }
                 
                  if ($page->rc_bot) {
                      print ' (<b>bot</b>)';
                  }
              ?>
            </span>
            <?
        }
        ?>
       
        <? if (@$page->tags): ?>
        <span class='tags'>
          (<?= printLinks($page->tags, $mode == 'cs' ? NS_CATEGORY : NS_TEMPLATE ) ?>)
        </span>
        <? endif; ?>
      </span>
    </td>
  </tr>
  <?
 
  return $n;
}

function printArticleCSV($page) {
    print $page->page_namespace;
    print "\t";
    print $page->page_title;
    print "\t";
    print @$page->cats;
    print "\t";
    print @$page->tags;
   
    print "\t";
    print @$page->page_id;
   
    if (@$page->rc_last_oldid) {
        print "\t";
        print $page->rc_last_oldid;
    }
   
    if (@$page->rc_this_oldid) {
        print "\t";
        print $page->rc_this_oldid;
    }
   
    print "\r\n";
}

function printArticleWiki($page, $mode) {
    global $wiki;

    $n = $wiki->asUrlName($page->page_namespace, $page->page_title);

    $pre = $page->page_namespace == NS_CATEGORY || $page->page_namespace == NS_IMAGE ? ":" : "";

    print "* [[$pre$n]]";

    if (@$page->cats) {
        print ": ";
        printWikiLinks($page->cats, NS_CATEGORY);
    }

    if (@$page->tags) {
        if (@$page->cats) print "; ";
        else print ": ";
        printWikiLinks($page->tags, $mode == 'cs' ? NS_CATEGORY : NS_TEMPLATE);
    }
   
    print "\n";
}

function makeSQLSet($titles) {
    global $db;
   
    if (!is_array($titles)) {
        $titles= preg_split('! *[;/\|] *!',$titles);
    }
   
    $s= '';
    foreach ($titles as $t) {
        if ($s) $s.= ', ';
        $t= wsfDBTitle($t);
        $s.= $db->addQuotes($t);
    }
   
    return $s;
}

function listArticles( $base, $filter, $mode= 'cs', $inverse= false ) {
  global $db, $format, $wiki, $commons;
 
  if (!$filter) { #list all articles in categories
 
      #print "COMMONS DB: ".$commons->dbname;
 
      if ( $mode == 'il') { #categorized images
        $sql= "SELECT page_id, page_namespace, page_title, page_restrictions,
                        group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats,
                        if(local.img_size IS NULL,1,0) as on_commons,
                        if(local.img_width IS NOT NULL, local.img_width, commons.img_width) as img_width,
                        if(local.img_height IS NOT NULL, local.img_height, commons.img_height) as img_height,
                        if(local.img_size IS NOT NULL, local.img_size, commons.img_size) as img_size,
                        if(local.img_major_mime IS NOT NULL, local.img_major_mime, commons.img_major_mime) as img_major_mime,
                        if(local.img_minor_mime IS NOT NULL, local.img_minor_mime, commons.img_minor_mime) as img_minor_mime
                FROM page
                JOIN categorylinks as c ON c.cl_from = page_id
                LEFT JOIN image as local ON page_title = local.img_name
                LEFT JOIN "
.$commons->dbname.".image as commons ON page_title = commons.img_name
                WHERE page_namespace = "
.NS_IMAGE." AND c.cl_to in (".makeSQLSet($base).")
                GROUP BY page_title
                ORDER BY page_title"
;
      }
      else if ( $mode == 'iul') { #categorized and used images
        /*$sql= "SELECT ".NS_IMAGE." as page_namespace, il_to as page_title,
                        group_concat(DISTINCT page_title SEPARATOR '|') as used_in,
                        group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats,
                        if(local.img_size IS NULL,1,0) as on_commons,
                        if(local.img_width IS NOT NULL, local.img_width, commons.img_width) as img_width,
                        if(local.img_height IS NOT NULL, local.img_height, commons.img_height) as img_height,
                        if(local.img_size IS NOT NULL, local.img_size, commons.img_size) as img_size,
                        if(local.img_major_mime IS NOT NULL, local.img_major_mime, commons.img_major_mime) as img_major_mime,
                        if(local.img_minor_mime IS NOT NULL, local.img_minor_mime, commons.img_minor_mime) as img_minor_mime
                FROM imagelinks
                LEFT JOIN image as local ON il_to = local.img_name
                LEFT JOIN ".$commons->dbname.".image as commons ON il_to = commons.img_name
                JOIN page ON il_from = page_id
                JOIN categorylinks as c ON c.cl_from = page_id
                WHERE c.cl_to in (".makeSQLSet($base).")
                AND page_namespace = ".NS_MAIN."
                AND page_is_redirect = 0
                GROUP BY il_to
                ORDER BY il_to";*/

               
        $sql= " SELECT page_namespace, page_title, page_restrictions,
                       group_concat(DISTINCT cat SEPARATOR '|') as cats,
                       group_concat(DISTINCT art SEPARATOR '|') as used_in,
                       if(local.img_size IS NULL,1,0) as on_commons,
                       if(local.img_width IS NOT NULL, local.img_width, commons.img_width) as img_width,
                       if(local.img_height IS NOT NULL, local.img_height, commons.img_height) as img_height,
                       if(local.img_size IS NOT NULL, local.img_size, commons.img_size) as img_size,
                       if(local.img_major_mime IS NOT NULL, local.img_major_mime, commons.img_major_mime) as img_major_mime,
                       if(local.img_minor_mime IS NOT NULL, local.img_minor_mime, commons.img_minor_mime) as img_minor_mime
              FROM
              ( SELECT page_namespace, page_title, page_restrictions,
                       NULL as art,
                       c.cl_to as cat
                FROM page
                JOIN categorylinks as c ON c.cl_from = page_id
                WHERE page_namespace = "
.NS_IMAGE." AND c.cl_to in (".makeSQLSet($base).")
               
              UNION
                SELECT "
.NS_IMAGE." as page_namespace, il_to as page_title,
                        NULL as page_restrictions, "
. /* #FIXME: join with img-page to get page_restrictions field! */ "
                        page_title as art,
                        c.cl_to as cat
                FROM imagelinks
                JOIN page ON il_from = page_id
                JOIN categorylinks as c ON c.cl_from = page_id
                WHERE c.cl_to in ("
.makeSQLSet($base).")
                AND page_namespace = "
.NS_MAIN."
                AND page_is_redirect = 0
              ) as img
              LEFT JOIN image as local ON page_title = local.img_name
              LEFT JOIN "
.$commons->dbname.".image as commons ON page_title = commons.img_name
              GROUP BY page_title
              ORDER BY page_title"
;
      }
      else {
        $sql= "SELECT page_id, page_namespace, page_title, page_restrictions,
                        group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats
                FROM page
                JOIN categorylinks as c ON c.cl_from = page_id
                WHERE c.cl_to in ("
.makeSQLSet($base).")
                GROUP BY page_id
                ORDER BY page_title"
;
      }
  }
  else if ($mode=='rc') {
    if (!is_array($filter)) $filter= array('hours'=>$filter);
   
    $h= (int)$filter['hours'];
    $t= time() - ($h * 60 * 60);
   
    $t= wfTimestamp(TS_MW,$t);
   
    $where= '';
   
    if (@$filter['nobots']) $where.= ' AND rc_bot = 0 ';
    if (@$filter['nominor']) $where.= ' AND rc_minor = 0 ';
    if (@$filter['onlynew']) $where.= ' AND rc_new = 1 ';
   
    #print_r($filter);
   
    #TODO: join with page table to get page_restrictions!
    $sql= "SELECT rc_title as page_title,
                  rc_namespace as page_namespace,
                  rc_cur_id as page_id,
                  rc_type, rc_timestamp, rc_user_text, rc_comment,
                  rc_minor, rc_bot, rc_new,
                  rc_this_oldid, rc_last_oldid,
                  group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats
           FROM "
.$wiki->getTableName('recentchanges')."
           JOIN categorylinks as c ON c.cl_from = rc_cur_id
           WHERE rc_timestamp > "
.$db->addQuotes($t)."
                 $where
           AND c.cl_to in ("
.makeSQLSet($base).")
           GROUP BY rc_id
           ORDER BY rc_timestamp DESC"
;
 
    /*$sql= "SELECT page_id, page_namespace, page_title,
                  group_concat(r.rev_user_text SEPARATOR '|') as users,
                  group_concat(r.rev_timestamp SEPARATOR '|') as times,
                  group_concat(r.rev_id SEPARATOR '|') as ids,
                  group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats
            FROM page
            JOIN categorylinks as c ON c.cl_from = page_id
            JOIN revision as r ON page_latest = r.rev_id
            WHERE c.cl_to in (".makeSQLSet($base).")
            AND   r.rev_timestamp > ".$db->addQuotes($t)."
            GROUP BY page_id
            ORDER BY page_title";
    */

  }
  else if ($mode == 'ss') {
      /*
      $size= (int)$filter;
 
      if ( $inverse ) { #bigger
          $where= 'page_len >= '.$size;
      }
      else { #smaller
          $where= 'page_len < '.$size;
      }
   
      $sql= "SELECT page_id, page_namespace, page_title, page_len,
                    group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats
            FROM page
            JOIN categorylinks as c ON c.cl_from = page_id
            WHERE c.cl_to in (".makeSQLSet($base).")
            AND page_namespace = ".NS_MAIN."
            AND page_is_redirect = 0
            AND ".$where."
            GROUP BY page_id
            ORDER BY page_title";
      */

      if (!is_array($filter)) $filter= array('hours'=>$filter);
      $size= $filter['size'] ? (int)$filter['size'] : NULL;
      $links= $filter['links'] ? (int)$filter['links'] : NULL;
     
      $where= '';
      $left= '';
      $having= '';
 
      $op= @$filter['stubop'] ? $filter['stubop'] : 'or';
     
      if ($size && $links) {
          if ($op=='and') {
              $where.= ' page_len < '.$size;
              $having.= ' HAVING links < '.$links;
          }
          else {
              $having.= ' HAVING links < '.$links.' OR page_len < '.$size;
          }
      }
      else if ($size) $where.= ' page_len < '.$size;
      else if ($links) $having.= ' HAVING links < '.$links;
     
      if ($links) {
          $left= 'LEFT ';
          if ($where) $where.= ' AND ';
          $where.= 'pl_namespace = '.NS_MAIN;
      }
   
      $sql= "SELECT page_id, page_namespace, page_title, page_restrictions, page_len,
                    "
.($links?"count(DISTINCT t.pl_title) as links, ":"")."
                    group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats
            FROM page
            JOIN categorylinks as c ON c.cl_from = page_id
            "
.($links?"$left JOIN pagelinks as t on t.pl_from = page_id ":"")."
            WHERE c.cl_to in ("
.makeSQLSet($base).")
            AND page_namespace = "
.NS_MAIN."
            AND page_is_redirect = 0
            AND "
.$where."
            GROUP BY page_id
            $having
            ORDER BY page_title"
;
  }
  else if ($mode == 'ls') {
      $links= (int)$filter;
 
      if ( $inverse ) { #more
          $having= 'links >= '.$links;
          $left= '';
      }
      else { #smaller
          $having= 'links < '.$links;
          $left= 'LEFT ';
      }
   
      $sql= "SELECT page_id, page_namespace, page_title, page_restrictions,
                    group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats,
                    count(DISTINCT t.pl_title) as links
            FROM page
            JOIN categorylinks as c ON c.cl_from = page_id
            $left JOIN pagelinks as t on t.pl_from = page_id
            WHERE c.cl_to in ("
.makeSQLSet($base).")
            AND pl_namespace = "
.NS_MAIN."
            AND page_namespace = "
.NS_MAIN."
            AND page_is_redirect = 0
            GROUP BY page_id
            HAVING $having
            ORDER BY page_title"
;
  }
  else {
      if ( $mode == 'al') { #highlite
          $filterHaving= '';
      }
      else if ( $inverse ) { #without
          $filterHaving= 'HAVING tags IS NULL';
      }
      else { #with
          $filterHaving= 'HAVING tags IS NOT NULL';
      }
   
      if ( $mode == 'cs' ) {
          $sql= "SELECT page_id, page_namespace, page_title, page_restrictions,
                        group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats,
                        group_concat(DISTINCT if (t.cl_to in ("
.makeSQLSet($filter)."), t.cl_to, null) SEPARATOR '|') as tags
                FROM page
                JOIN categorylinks as c ON c.cl_from = page_id
                JOIN categorylinks as t on t.cl_from = page_id
                WHERE c.cl_to in ("
.makeSQLSet($base).")
                GROUP BY page_id
                $filterHaving
                ORDER BY page_title"
;
      }
      else {
          $left= '';
          if ( $mode == 'al' ) $left= 'LEFT';
         
          $sql= "SELECT page_id, page_namespace, page_title, page_restrictions,
                        group_concat(DISTINCT c.cl_to SEPARATOR '|') as cats,
                        group_concat(DISTINCT if (t.tl_title in ("
.makeSQLSet($filter)."), t.tl_title, null) SEPARATOR '|') as tags
                FROM page
                JOIN categorylinks as c ON c.cl_from = page_id
                $left JOIN templatelinks as t on t.tl_from = page_id
                WHERE c.cl_to in ("
.makeSQLSet($base).")
                GROUP BY page_id
                $filterHaving
                ORDER BY page_title"
;
      }
  }
 
  if ($format=='html') $sql.= " LIMIT 1000";
 
         
  #AND page_namespace = ".NS_MAIN."
         
  #print "*** $sql ***";
 
  $res= $db->query($sql, 'getSubcategories');         
  $c= 0;

  if ($format=='html') print "\n<table>\n";
 
  while ($page= $db->fetchObject($res)) {
         if ($format=='wiki') printArticleWiki($page, $mode); #FIXME: gallery, if $mode=='il' || $mode=='iul'
    else if ($format=='csv') printArticleCSV($page);
    else if ($mode=='il' || $mode=='iul') printImageHTML($page);
    else printArticleHTML($page, $mode);
   
    $c+= 1;
  }
 
  if ($format=='html') {
    if ($c==1000) print "<tr><td colspan='2'><p class='error'>Search aborted after 1000 entries!</p></td></tr>";
    print "\n</table>\n";
  }

  $db->freeResult($res);
 
  return $c;
}

function getDeepCategories( $cats, $depth= 2, $max= 512 ) {
    global $wsgCatScanText, $db;

    if (!is_array($cats)) {
        $todo= preg_split('! *[;/\|] *!',$cats);
    }
    else $todo= $cats;
   
    if ($depth<=1) return $todo;
    if ($depth>100) $depth= 100;
    if ($max>1024) $max= 1024;
   
    wsfLog($wsgCatScanText->msg('recursing_categories'),LL_INFO);
   
    $key= implode('|',$todo);
   
    $done= array();
    $i= 0;
   
    while ($todo && $i<$depth && sizeof($done)<$max) {
        $i+= 1;
       
        collectDeepCategories( $todo, $done, "collectDeepCategories($key, $i)", "Subcategories of $key, level $i" );
    }
   
    if ($todo && $i<$depth) wsfLog("WARNING: scan aborted after ".sizeof($done)." categories ($i levels)",LL_WARN);
   
    return $done;
}

function collectDeepCategories( &$todo, &$done, $cachekey=NULL, $cachedescr=NULL) {
  global $db;
 
  if (!$todo) return array();
 
  $data= false;
  $cache= NULL;
 
  if ($cachekey) {
      $cache=& QCache::newWithoutQuery($db->getProperty('mDBname'), "collectDeepCategories", $cachedescr, 60*60*24, $cachekey);
      #$cache->debug= true;
     
      $data= $cache->load( true );
  }
 
  if ( $data===false ) {
      $sql= "SELECT page_title
            FROM page
            JOIN categorylinks ON cl_from = page_id
            WHERE cl_to in ("
. makeSQLSet($todo) . " )
            AND page_namespace = "
.NS_CATEGORY."
            AND page_is_redirect = 0"
;
           
      $res= $db->query($sql, 'getDeepCategories');   
     
      $found= array();
      $data= array();
      while ( $row= $db->fetchRow($res) ) {
        if ( $cache && $cache->cacheDB ) $data[]= $row;
        $found[]= $row['page_title'];
      }
 
      $db->freeResult($res);
     
      if ( $cache && $cache->cacheDB ) {
          $cache->putData( $data );
      }
  }
  else {
      wsfLog("NOTE: using cached results for $cachedescr, {$cache->queryRecord->age} seconds old",LL_WARN);
     
      $found= array();
      foreach ($data as $row) {
        $found[]= $row['page_title'];
      }
  }
 
  $done= array_merge($done,$todo);
  $todo= array_diff($found,$done);
 
  return $found;
}

function getOnChangeToggleJS($enable, $disable = NULL) {
  global $paramFields;

  if (is_null($disable)) {
      if ($enable) $disable= array_diff($paramFields, $enable);
      else $disable= $paramFields;
  }

  if (!$enable && !$disable) return '';
 
  return ' onchange="'.escapeHtml(getSetDisabledJS($enable,false)).escapeHtml(getSetDisabledJS($disable,true)).'" ';
}

function getSetDisabledJS ($ids, $value) {
    if (!$ids) return '';
   
    if ($value) $value= 'true';
    else $value= 'false';
   
    $js= 'setDisabled( new Array(';
       
    $first= true;
    foreach($ids as $id) {
        if ($first) $first= false;
        else $js.= ', ';
       
        $js.= '\''.addslashes($id).'\'';
    }
   
    $js.="), $value); ";
   
    return $js;
}

$knownLanguages= array('ar', 'bg', 'ca', 'da', 'de', 'el', 'en', 'eo', 'es', 'fi', 'fr', 'gl', 'he', 'hr', 'hu', 'it', 'ja', 'lt', 'mk', 'nds', 'nl', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'th', 'uk', 'vi', 'zh-cn', 'zh-hant');
$wsgCatScanText=& WikiSenseLocalizer::initialize('CatScan', $knownLanguages, $wgRequest->getVal('set-userlang'));

$wikiSelector= new WikiSelector();

$mode= $wgRequest->getVal('mode','cs');
$basecat= $wgRequest->getVal('basecat');
$basedeep= $wgRequest->getVal('basedeep',3);
$tagcat= $wgRequest->getVal('tagcat');
$templates= $wgRequest->getVal('templates');
$tagdeep= $wgRequest->getVal('tagdeep',3);
$untagged= $wgRequest->getVal('untagged');
$size= $wgRequest->getVal('size',512);
$links= $wgRequest->getVal('links',4);
$stubop= $wgRequest->getVal('stubop','or');
$hours= $wgRequest->getVal('hours',12);
$nominor= $wgRequest->getVal('nominor');
$nobots= $wgRequest->getVal('nobots');
$onlynew= $wgRequest->getVal('onlynew');

$filterMode= $wgRequest->getVal('filter','w');

$terse= $wgRequest->getVal('terse');
$conf= $wgRequest->getVal('conf');

$defFormat = $wgRequest->getVal('raw',0) ? 'csv' : 'html';
$format= $wgRequest->getVal('format', $defFormat );


$db= NULL;

if ($basecat) $basecat= trim($basecat);
if ($tagcat) $tagcat= trim($tagcat);

if ($hours && $hours>24*30) $hours= 24*30;
if ($basedeep && $basedeep>100) $basedeep= 100;
if ($tagdeep && $tagdeep>100) $tagdeep= 100;

$doquery= false;

if ( $wikiSelector->domain && $mode ) {
    if ($mode=='cs' && $tagcat) {
      $doquery= true;
    }
    else if ($mode=='ts' && $templates) {
      $doquery= true;
    }
    else if ($mode=='ss' && ($size || $links)) {
      $doquery= true;
    }
    else if ($mode=='ls' && $links) {
      $doquery= true;
    }
    else if ($mode=='rc' && $hours) {
      $doquery= true;
    }
    else if ($mode=='cl' || $mode=='al') {
      $doquery= true;
    }
    else if ($mode=='il' || $mode=='iul') {
      $doquery= true;
    }
}

$commons= NULL;
$wiki= NULL;

if ( $wikiSelector->domain ) {
  $wiki= WikiAccess::newInstance($wikiSelector->domain);
  if ($wiki) {
      $db=& $wiki->wikiDB;
  }
 
  if ($mode=='il' || $mode=='iul') {
      $commons= WikiAccess::newInstance('commons.wikimedia.org');
  }
}

if ($doquery && $format!='html') {
  #header("Content-Type: text/csv; charset=utf-8");
  header("Content-Type: text/plain; charset=utf-8");
 
  $wsgLogLevel= LL_MUTE;
 
  if ($basedeep && $basedeep>1 && $basecat) $basecat= getDeepCategories($basecat,$basedeep);
  if ($tagdeep && $tagdeep>1 && $tagcat) $tagcat= getDeepCategories($tagcat,$tagdeep);
 
  if ($mode=='cs') listArticles( $basecat, $tagcat, $mode );
  else if ($mode=='ts') $c= listArticles( $basecat, $templates, $mode, $untagged );
  else if ($mode=='ss') $c= listArticles( $basecat, array('size'=>$size, 'links'=>$links, 'stubop'=>$stubop), $mode );
  else if ($mode=='ls') $c= listArticles( $basecat, $links, $mode );
  else if ($mode=='al') $c= listArticles( $basecat, $templates, $mode );
  else if ($mode=='rc') $c= listArticles( $basecat, array('hours'=>$hours, 'onlynew'=>$onlynew, 'nominor'=>$nominor, 'nobots'=>$nobots), $mode );
  else if ($mode=='il' || $mode=='iul') $c= listArticles( $basecat, NULL, $mode );
  else if ($mode=='cl') {
      if (!is_array($basecat)) $basecat= array($basecat);
      sort($basecat);
     
      foreach ($basecat as $cat) {
          $p= new stdClass();
         
          @$p->page_title= $cat;
          @$p->page_namespace= NS_CATEGORY;
         
          if ($format == 'csv') printArticleCSV($p);
          else if ($format == 'wiki') printArticleWiki($p, $mode);
      }
  }
 
  exit;
}

$paramFields= array('tagcat','tagdeep','templates','untagged','size','links','stubop','hours','nobots','nominor','onlynew');

$formats = array(
        'html' => $wsgCatScanText->msg('format_html'),
        'csv' => $wsgCatScanText->msg('format_csv'),
        'wiki' => $wsgCatScanText->msg('format_wiki'),
);

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" lang="en" xml:lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Cat Scan</title>
 
  <?
  if ($doquery) 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; }
                       
    .sectionhead { font-weight:bold; white-space:nowrap; }
    .parent { font-weight:bold; font-style:italic; }
    .leaf { font-weight:normal; margin-left:3ex; }
    /* .settings input[type=text] { width:48ex; } */
    /* .settings select { font-size:80%; } */
 
    .cell { padding:0.5ex; background-color:#EEEEEE; vertical-align:top; }
    .thumb { border:1px solid #AAAAAA; padding:0.5ex; background-color:#EEEEEE; }
   
    .error { font-weight:bold; color:red; }
 
    .loaded { color:black; text-decoration: none; }
    .content { margin-left:2ex; }
    .links { font-weight:normal; font-size:80%; }
    .tags { font-weight:normal; font-style:italic; font-size:72%; background-color:yellow; }
    .cell .tags { font-weight:normal; font-style:italic; font-size:72%; background-color:#F0F0FF; }
    .log { font-weight:normal; font-style:normal; font-size:72%; }
    .cats { font-weight:normal; font-style:italic; font-size:72%; background-color:#F0FFF0; text-align:right; }
    .tags a:link { color:inherit; text-decoration:none; }
    .cats a:link { color:inherit; text-decoration:none; }
    .tags a:visited { color:inherit; text-decoration:none; }
    .cats a:visited { color:inherit; text-decoration:none; }
    .tags a:hover { text-decoration:underline; }
    .cats a:hover { text-decoration:underline; }
    .highlite { background-color:yellow; }
    .restrictions_edit_sysop { color:#CC0000; font-style:italic; font-weight:bold; }
    .restrictions_edit_autoconfirmed { color:#FF6666; font-style:italic; }
   
    img { font-size:72%; }
   
    /*.settings {
        border:1px solid #AAAAAA;
        background-color: #EEEEEE;
        padding:0 1ex 1ex 1ex;
        margin:0;
        margin-bottom:1ex;
    }*/

   
  </style>

  <script type="text/javascript">
      function setDisabled(ids, disabled) {
          if (!document.params) return;
         
          //alert("setDisabled(("+ids+"),"+disabled+")");
     
          for (var n=0; n<ids.length; n++) {
              var id= ids[n];
              var e= document.params[id];
             
              if (e) {
                  if (typeof e == 'array') {
                      for (var m=0; m<e.length; m++) {
                          e[m].disabled= disabled;
                      }
                  }
                  else e.disabled= disabled;
              }
              //else alert('NOT FOUND: ['+n+']='+id);
          }
      }
     
      function init() {
          if (!document.params) {
              alert("form not found!");
              return;
          }
         
          for (var n=0; n<document.params.elements.length; n++) {
              var e= document.params.elements[n];
             
              if (typeof e == 'array') {
                  for (var m=0; m<e.length; m++) {
                      if (e[m].checked) e[m].onchange();
                  }
              }
              else if (e.checked) e.onchange();
          }
      }
  </script>
</head>

<body>
  <? wsfHeader(); ?>
  <div id='content'>
  <h1>CatScan</h1>
  <? wsfSubtitle('CatScan'); ?>
  <?
    $lag= wsfGetReplagHTML();
    if ($lag) print "<div class='replag'>$lag</div>";
  ?>
   
  <form action="CategoryIntersect.php" name="params">
 
    <div style='position:relative; top:0; left:0; float:left; margin-left:auto; margin-right:auto;' class='querybox'>
    <table class='settings'>
      <tr><td>
          <?= $wsgCatScanText->msg('wiki') ?>
      </td><td>
          <? $wikiSelector->printSelector(false); ?>
      </td></tr>
     
      <tr><td>
          <b><?= $wsgCatScanText->msg('search_in_category') ?></b>
      </td><td>
          <input type="text" name="basecat" value="<?=escapeHtml($basecat)?>" size="48"/>
          <?= $wsgCatScanText->msg('with_depth') ?> <input type="text" name="basedeep" value="<?=escapeHtml($basedeep)?>" size="2"/>
      </td></tr>
     
      <tr><td>
          <?= printRadioButton('mode','cs',$mode,getOnChangeToggleJS(array('tagcat','tagdeep'))) ?>
          <?= $wsgCatScanText->msg('for_pages_by_category') ?>
      </td><td>
          <input type="text" name="tagcat" value="<?=escapeHtml($tagcat)?>" size="48"/>
          <?= $wsgCatScanText->msg('with_depth') ?> <input type="text" name="tagdeep" value="<?=escapeHtml($tagdeep)?>" size="2"/>
      </td></tr>
     
      <tr><td>
          <?= printRadioButton('mode','ts',$mode,getOnChangeToggleJS(array('templates','untagged'))) ?>
          <?= $wsgCatScanText->msg('for_pages_by_template') ?>
      </td><td>
          <input type="text" name="templates" value="<?=escapeHtml($templates)?>" size="48"/>
          <?= $wsgCatScanText->msg('inverse') ?> <? printCheckbox('untagged',$untagged) ?> (<?= $wsgCatScanText->msg('untagged_only') ?>)
      </td></tr>
     
      <tr><td>
          <?= printRadioButton('mode','al',$mode,getOnChangeToggleJS(array('templates'))) ?>
          <?= $wsgCatScanText->msg('for_all_pages') ?>
      </td><td>
          <small><?= $wsgCatScanText->msg('all_pages_hint') ?></small>
      </td></tr>
     
      <tr><td>
          <?= printRadioButton('mode','ss',$mode,getOnChangeToggleJS(array('size','links','stubop'))) ?>
          <?= $wsgCatScanText->msg('for_stubs') ?>
      </td><td>
          <?= $wsgCatScanText->msg('having_less_than_x_bytes_1','<input type="text" name="size" value="'.escapeHtml($size).'" size="6"/>') ?>
          <select name='stubop'>
              <? printOption($wsgCatScanText->msg('and'), 'and', $stubop); ?>
              <? printOption($wsgCatScanText->msg('or'), 'or', $stubop); ?>
          </select>
          <?= $wsgCatScanText->msg('less_than_x_links_1','<input type="text" name="links" value="'.escapeHtml($links).'" size="3"/>') ?>
          (<?= $wsgCatScanText->msg('main_namespace_only') ?>)
      </td></tr>
     
      <!--<tr><td>
          <?/*= printRadioButton('mode','ls',$mode,getOnChangeToggleJS(array('links')))*/ ?>
          for articles with less than
      </td><td>
          <input type="text" name="links" value="<?=escapeHtml($links)?>" size="3"/> links (main namespace only);
      </td></tr>-->
     
      <tr><td>
          <?= printRadioButton('mode','rc',$mode,getOnChangeToggleJS(array('hours','nominor','nobots','onlynew'))) ?>
          <?= $wsgCatScanText->msg('for_changes_in_the_last') ?>
      </td><td>
          <input type="text" name="hours" value="<?=escapeHtml($hours)?>" size="3"/> <?= $wsgCatScanText->msg('hours') ?>,
          <?= $wsgCatScanText->msg('hide_minor') ?> <? printCheckbox('nominor',$nominor) ?>,
          <?= $wsgCatScanText->msg('hide_bots') ?> <? printCheckbox('nobots',$nobots) ?>,
          <?= $wsgCatScanText->msg('only_new') ?> <? printCheckbox('onlynew',$onlynew) ?>
      </td></tr>
     
      <tr><td>
          <?= printRadioButton('mode','iul',$mode,getOnChangeToggleJS(NULL)) ?>
          <?= $wsgCatScanText->msg('for_all_images') ?>
      </td><td>
          &nbsp;
      </td></tr>
     
      <!--
      <tr><td>
          <?/*= printRadioButton('mode','il',$mode,getOnChangeToggleJS(NULL))*/ ?>
          for images in categories
      </td><td>
          &nbsp;
      </td></tr>
      -->
     
      <tr><td>
          <?= printRadioButton('mode','cl',$mode,getOnChangeToggleJS(NULL)) ?>
          <?= $wsgCatScanText->msg('for_all_categories') ?>
      </td><td>
          &nbsp;
      </td></tr>
     
      <tr><td colspan="2" align="center">
          <input type="submit" name="<?= $conf?'configure':'go' ?>" value="<?= $wsgCatScanText->msg('catscan_go') ?>"/>
          &nbsp; &nbsp; <label for="format"><?= $wsgCatScanText->msg('select_format'); ?></label> <? printSelector('format', $formats, $format); ?>
         
          <div style='top:-9ex; right:0; position:absolute;'>
              <? $wsgCatScanText->printLanguageSelector($knownLanguages); ?>
              <input type="submit" name="set-userlang" value="<?= $wsgCatScanText->msg('set_language') ?>"/>
              <br/><? $wsgCatScanText->printTranslationLink('CatScan') ?>
          </div>
      </td></tr>
    </table>
    </div>
   
    <? if ($terse): ?>
    <input type="hidden" name="terse" value="<?= escapeHtml($terse) ?>"/>
    <? endif; ?>
  </form>
  </div>
 
  <script type='text/javascript'>
      init();
  </script>
 
  <br style='clear:both;'>
   
  <?
  flush();
 
  if ($basecat) {
      $c= $basecat;
      $w= '';
     
      if (is_array($basecat)) {
        if (sizeof($basecat)>1) $c= NULL;
        else $c= $basecat[0];
      }
     
      if (!is_array($basecat) && strpos($basecat,'|')!==false) $c= NULL;
     
      if ($c) $label= $wsgCatScanText->msg('category_as_tree_1', escapeHtml($c));
      else $label= $wsgCatScanText->msg('category_tree');
     
      if ($wikiSelector->wikiInfo) $w= $wikiSelector->appendUrlParameters($w);
      if ($c) $c= '&amp;cat='.urlencode($c);
 
      print "<p style='font-size:90%'><a href='CategoryTree.php?$w$c'>$label</a></p>";
  }
 
  $c= 0;
 
  if ($doquery) {
    if ($basedeep && $basedeep>1 && $basecat) $basecat= getDeepCategories($basecat,$basedeep);
    if ($tagdeep && $tagdeep>1 && $tagcat) $tagcat= getDeepCategories($tagcat,$tagdeep);
   
    if ($mode=='cs' && $tagcat) {
        print '<h3>'.$wsgCatScanText->msg('category_intersection_2',escapeHtml($wgRequest->getVal('basecat')),escapeHtml($wgRequest->getVal('tagcat'))).':</h3>';
        $c= listArticles( $basecat, $tagcat, $mode );
    }
    else if ($mode=='ts' && $templates) {
        print '<h3>'.$wsgCatScanText->msg($untagged?'untagged_in_category_2':'tagged_in_category_2',escapeHtml($wgRequest->getVal('basecat')),escapeHtml($wgRequest->getVal('templates'))).':</h3>';
       
        #print '<p style="background-color:#FFFFAA; border:2px solid red; padding:1ex; margin-left:auto; margin-right:auto; width:80%; text-align:center;">
        #          <b>Warning:</b> there seem to be some problems with the templatelinks table currently.
        #          Some pages may be reported as untagged, while they are in fact contain a template. This will hopefully be fixed soon. </p>';

        $c= listArticles( $basecat, $templates, $mode, $untagged );
    }
    else if ($mode=='ss' && ($size || $links)) {
        if ($size && $links) $s= $wsgCatScanText->msg('stubs_under_4',escapeHtml($wgRequest->getVal('basecat')),escapeHtml($wgRequest->getVal('size')),$wsgCatScanText->msg($stubop),escapeHtml($wgRequest->getVal('links')));
        else if ($size) $s= $wsgCatScanText->msg('stubs_by_size_under_2',escapeHtml($wgRequest->getVal('basecat')),escapeHtml($wgRequest->getVal('size')));
        else if ($links) $s= $wsgCatScanText->msg('stubs_by_links_under_2',escapeHtml($wgRequest->getVal('basecat')),escapeHtml($wgRequest->getVal('links')));
       
        print "<h3>$s:</h3>";
   
        $c= listArticles( $basecat, array('size'=>$size, 'links'=>$links, 'stubop'=>$stubop), $mode );
    }
    /*else if ($mode=='ls' && $links) {
        print "<h3>$under and have ".(@$more?'at least':'less than')." <i>".escapeHtml($wgRequest->getVal('links'))."</i> links</h3>";
        $c= listArticles( $basecat, $links, $mode );
    }*/

    else if ($mode=='al') {
        if ($templates) {
            $s= ', '.$wsgCatScanText->msg('highliting_template',escapeHtml($wgRequest->getVal('templates')));
        }
        else $s= '';
       
        print "<h3>".$wsgCatScanText->msg('articles_under_1',escapeHtml($wgRequest->getVal('basecat'))).$s.":</h3>";
       
        #if ($templates) {
        #print '<p style="background-color:#FFFFAA; border:2px solid red; padding:1ex; margin-left:auto; margin-right:auto; width:80%; text-align:center;">
        #          <b>Warning:</b> there seem to be some problems with the templatelinks table currently.
        #          Some pages may be reported as untagged, while they are in fact contain a template. This will hopefully be fixed soon. </p>';
        #}
       
        $c= listArticles( $basecat, $templates, $mode );
    }
    else if ($mode=='rc') {
        print '<h3>'.$wsgCatScanText->msg('changes_in_2',escapeHtml($wgRequest->getVal('hours')),escapeHtml($wgRequest->getVal('basecat'))).':</h3>';
        $c= listArticles( $basecat, array('hours'=>$hours, 'nominor'=>$nominor, 'nobots'=>$nobots, 'onlynew'=>$onlynew), $mode );
    }
    else if ($mode=='iul') {
        print '<h3>'.$wsgCatScanText->msg('images_used_under_1',escapeHtml($wgRequest->getVal('basecat'))).':</h3>';
        $c= listArticles( $basecat, NULL, $mode );
    }
    else if ($mode=='il') {
        print '<h3>'.$wsgCatScanText->msg('images_under_1',escapeHtml($wgRequest->getVal('basecat'))).':</h3>';
        $c= listArticles( $basecat, NULL, $mode );
    }
    else if ($mode=='cl') {
        print '<h3>'.$wsgCatScanText->msg('categories_under_1',escapeHtml($wgRequest->getVal('basecat'))).':</h3>';
       
        ?>
        <table>
        <?
        if (!is_array($basecat)) $basecat= array($basecat);
        sort($basecat);
       
        foreach ($basecat as $cat) {
            $p= new stdClass();
           
            @$p->page_title= $cat;
            @$p->page_namespace= NS_CATEGORY;
           
            printArticleHTML($p,$mode);
        }
        ?>
        </table>
        <?
    }
   
    print "\n<p>";
   
    if ($mode=='cl') {
      print $wsgCatScanText->msg('found_categories_1',sizeof($basecat));
    }
    else if (!$c) {
      print $wsgCatScanText->msg('no_matches');
    }
    else {
      print $wsgCatScanText->msg('found_articles_1',$c);
    }
   
    print "\n</p>\n";
  }
 
  if ($wiki && is_object($wiki)) {
    $wiki->close();
  }
 
  ?>
  </div>
  <? wsfFooter(false); ?>
</body>

</html>