function execute($param)
 {
     global $wgOut;
     $this->setHeaders();
     $this->ranges = CategoryBrowser::generateRanges($this->source_ranges);
     $cb = new CategoryBrowser();
     # try to create rootPager from rootcond cookie value
     if (is_string($encPolishQueue = CB_Setup::getCookie('rootcond'))) {
         $sqlCond = CB_SqlCond::newFromEncodedPolishQueue($encPolishQueue);
         $rootPager = CB_RootPager::newFromSqlCond($sqlCond);
         # add selected condition to range, if not duplicate
         CategoryBrowser::addRange($this->ranges, $rootPager->sqlCond);
     } else {
         # otherwise, try to create rootPager from the list of predefined infix queues (ranges)
         if (!is_object($rootPager = CB_RootPager::newFromCategoryRange($this->ranges))) {
             return;
         }
     }
     $rootPager->getCurrentRows();
     /* reverse polish queue encode / decode validations */
     $testCond = CB_SqlCond::newFromEncodedPolishQueue($rootPager->sqlCond->getEncodedQueue(false));
     if ($rootPager->sqlCond->getCond() != $testCond->getCond()) {
         throw new MWException('Infix queue was not re-built correctly from encoded polish queue in ' . __METHOD__);
     }
     /* infix queue encode / decode validations */
     $testCond = CB_SqlCond::newFromEncodedInfixQueue($rootPager->sqlCond->getEncodedQueue(true));
     if ($rootPager->sqlCond->getCond() != $testCond->getCond()) {
         throw new MWException('Infix queue was not re-built correctly from encoded infix queue in ' . __METHOD__);
     }
     /* end of validations */
     # {{{ top template
     $condSelector = '';
     $catlist = array();
     $js_setFilter = 'CategoryBrowser.setFilter()';
     $filterFields = array();
     if (CB_Setup::$cat_title_CI != '') {
         // case insensitive search is possible
         $filterFields[] = array('__tag' => 'span', 0 => wfMsg('cb_cat_name_filter_ci'));
         $filterFields[] = array('__tag' => 'input', 'class' => 'cb_filter_field', 'type' => 'checkbox', 'onchange' => $js_setFilter, 'id' => 'cb_cat_name_filter_ci', 'title' => wfMsg('cb_cat_name_filter_ci'), 'checked' => null);
     }
     if (CB_Setup::$allowNoParentsOnly) {
         $filterFields[] = array(array('__tag' => 'span', 'class' => 'cb_filter_field', 0 => wfMsg('cb_show_no_parents_only')), array('__tag' => 'input', 'class' => 'cb_filter_field', 'type' => 'checkbox', 'onchange' => $js_setFilter, 'onclick' => $js_setFilter, 'title' => wfMsg('cb_show_no_parents_only'), 'id' => 'cb_cat_no_parents_only'));
     }
     $top_tpl = array('__tag' => 'table', 'class' => 'cb_top_container', '__end' => "\n", array('__tag' => 'tr', '__end' => "\n", array('__tag' => 'td', 'class' => 'cb_toolbox_top', '__end' => "\n", 0 => &$condSelector)), array('__tag' => 'tr', '__end' => "\n", array('__tag' => 'td', 'class' => 'cb_toolbox_bottom', '__end' => "\n", array('__tag' => 'div', 'class' => 'cb_filter_container', wfMsg('cb_cat_name_filter'), array('__tag' => 'input', 'type' => 'text', 'onkeyup' => $js_setFilter, 'onchange' => $js_setFilter, 'id' => 'cb_cat_name_filter'), array('__tag' => 'input', 'type' => 'button', 'class' => 'cb_filter_field', 'onclick' => 'CategoryBrowser.clearNameFilter(this)', 'title' => wfMsg('cb_cat_name_filter_clear'), 'value' => '※')), array('__tag' => 'div', 'class' => 'cb_filter_container', &$filterFields))), array('__tag' => 'tr', '__end' => "\n", array('__tag' => 'td', 'class' => 'cb_toolbox', 'style' => 'display:none; ', '__end' => "\n", array('__tag' => 'div', 'id' => 'cb_editor_container', 0 => ''), array('__tag' => 'div', 'class' => 'cb_separate_container', 0 => ''))), array('__tag' => 'tr', '__end' => "\n", array('__tag' => 'td', 'class' => 'cb_toolbox', 'style' => 'display:none; ', '__end' => "\n", array('__tag' => 'div', 'class' => 'cb_copy_line_hint', 0 => wfMsg('cb_copy_line_hint')), array('__tag' => 'div', 'id' => 'cb_samples_container', 0 => ''))), array('__tag' => 'tr', '__end' => "\n", array('__tag' => 'td', '__end' => "\n", array('__tag' => 'div', 'id' => 'cb_root_container', 0 => &$catlist))));
     # }}}
     $condSelector = CategoryBrowser::generateSelector($this->ranges, $rootPager);
     $pagerView = new CB_CategoriesView($rootPager);
     $catlist = $pagerView->generateList();
     $wgOut->addHTML(CB_XML::toText($top_tpl));
 }
 /**
  * called via AJAX to generate new selected option when the selected rootcond is new (the rootcond cookie was set)
  * @param $args[0] currently selected expression in encoded infix format
  */
 static function generateSelectedOption()
 {
     CB_Setup::initUser();
     $args = func_get_args();
     if (count($args) < 1) {
         throw new MWException('Argument 0 is missing in ' . __METHOD__);
     }
     $encInfixQueue = $args[0];
     $sqlCond = CB_SqlCond::newFromEncodedInfixQueue($encInfixQueue);
     $ranges = array();
     self::addRange($ranges, $sqlCond);
     # generate div instead of option to avoid innerHTML glitches in IE
     return self::generateOption($ranges[0], $sqlCond->getEncodedQueue(false), 'div');
 }
 /**
  * @param $token - encoded token object
  * @result - SQL token
  */
 private static function getSqlToken(stdClass $token)
 {
     switch ($token->type) {
         case 'comparsion':
             $matches = array();
             preg_match_all(CB_ENCODED_TOKEN_MATCH, $token->value, $matches, PREG_SET_ORDER);
             if (count($matches) == 1 && isset($matches[0]) && count($matches[0]) == 4) {
                 // decode comparsion op
                 return self::$sql_fields[$matches[0][2]] . ' ' . self::$sql_cmps[$matches[0][1]] . ' ' . (int) $matches[0][3];
             }
             break;
         case 'logical':
             if (in_array($token->value, self::$valid_logical_ops)) {
                 // decode logical op
                 // we store logical ops uppercase for the "prettiness"
                 return strtoupper($token->value);
             }
             break;
         case 'bracket':
             if (($opcode = array_search($token->value, self::$valid_bracket_ops)) !== false) {
                 // decode bracket op
                 return self::$valid_bracket_ops[$opcode];
             }
     }
     throw new MWException('Invalid operation type=' . CB_Setup::specialchars($token->type) . ' value=' . CB_Setup::specialchars($token->value) . ' in ' . __METHOD__);
 }
 /**
  * should not be called from LocalSettings.php
  * should be called only when the wiki is fully initialized
  */
 static function initUser()
 {
     global $wgUser, $wgRequest, $wgSkin;
     // TODO: add more encoding mappings
     $collation_CS_CI = array('utf8_bin' => 'utf8_general_ci');
     self::$user = is_object($wgUser) ? $wgUser : new User();
     self::$skin = is_object($wgUser) ? self::$user->getSkin() : $wgSkin;
     self::$response = $wgRequest->response();
     self::$cookie_prefix = 'CategoryBrowser_' . self::$user->getId() . '_';
     # find out current collation of category table 'cat_title' field
     # this is required to switch between CI and CS search
     $db =& wfGetDB(DB_SLAVE);
     $category_table = $db->tableName('category');
     $db_result = $db->query("SHOW FULL COLUMNS FROM {$category_table}");
     self::$cat_title_CI = '';
     $cat_title_CS = '';
     while ($row = $db->fetchObject($db_result)) {
         if ($row->Field == 'cat_title') {
             $cat_title_CS = $row->Collation;
             if (isset($collation_CS_CI[$cat_title_CS])) {
                 self::$cat_title_CI = $collation_CS_CI[$cat_title_CS];
             }
             break;
         }
     }
 }