/** * @return string html representation of question statistics */ public function displayStats( qp_SpecialPage $page, $pid ) { $ctrl = $this->ctrl; $current_title = $page->getTitle(); $output = $this->displayHeader() . "<div class=\"qpoll\">\n" . "<table class=\"qdata\">\n" . qp_Renderer::displayRow( array_map( array( $this, 'categoryentities' ), $ctrl->CategorySpans ), array( 'class' => 'spans' ), 'th', array( 'count' => 'colspan', 'name' => 0 ) ) . qp_Renderer::displayRow( array_map( array( $this, 'categoryentities' ), $ctrl->Categories ), array(), 'th', array( 'name' => 0 ) ); # multiple choice polls doesn't use real spans, instead, every column is like "span" $spansUsed = count( $ctrl->CategorySpans ) > 0 || $ctrl->type == "multipleChoice"; foreach ( $ctrl->ProposalText as $propkey => &$proposal_text ) { if ( isset( $ctrl->Votes[ $propkey ] ) ) { if ( $ctrl->Percents === null ) { $row = $ctrl->Votes[ $propkey ]; } else { $row = $ctrl->Percents[ $propkey ]; foreach ( $row as $catkey => &$cell ) { # Replace spaces with en spaces $formatted_cell = str_replace( " ", " ", sprintf( '%3d%%', intval( round( 100 * $cell ) ) ) ); # only percents !=0 are displayed as link if ( $cell == 0.0 && $ctrl->question_id !== null ) { $cell = array( 0 => $formatted_cell, "style" => "color:gray" ); } else { $cell = array( 0 => $page->qpLink( $current_title, $formatted_cell, array( "title" => wfMsgExt( 'qp_votes_count', array( 'parsemag' ), $ctrl->Votes[ $propkey ][ $catkey ] ) ), array( "action" => "qpcusers", "id" => $pid, "qid" => $ctrl->question_id, "pid" => $propkey, "cid" => $catkey ) ) ); } if ( $spansUsed ) { if ( $ctrl->type == "multipleChoice" ) { $cell[ "class" ] = ( ( $catkey & 1 ) === 0 ) ? "spaneven" : "spanodd"; } else { $cell[ "class" ] = ( ( $ctrl->Categories[ $catkey ][ "spanId" ] & 1 ) === 0 ) ? "spaneven" : "spanodd"; } } else { $cell[ "class" ] = "stats"; } } } } else { # this proposal has no statistics (no votes) $row = array_fill( 0, count( $ctrl->Categories ), '' ); } $row[] = array( 0 => qp_Setup::entities( $proposal_text ), "style" => "text-align:left;" ); $output .= qp_Renderer::displayRow( $row ); } $output .= "</table>\n" . "</div>\n"; return $output; }
/** * Add category as select / option list tagarray */ function addSelect( stdClass $elem, $className ) { if ( $elem->options[0] !== '' ) { # default element in select/option set always must be an empty option array_unshift( $elem->options, '' ); } $html_options = array(); # prepare the list of selected values if ( $elem->attributes['multiple'] !== null ) { # new lines are separator for selected multiple options $selected_values = explode( qp_Setup::SELECT_MULTIPLE_VALUES_SEPARATOR, $elem->value ); } else { $selected_values = array( $elem->value ); } # generate options list foreach ( $elem->options as $option ) { $html_option = array( '__tag' => 'option', 'value' => qp_Setup::entities( $option ), qp_Setup::specialchars( $option ) ); if ( in_array( $option, $selected_values ) ) { $html_option['selected'] = 'selected'; } $html_options[] = $html_option; } $select = array( '__tag' => 'select', # unique (poll_type,order_id,question,proposal,category) "coordinate" for javascript 'id' => "{$this->id_prefix}c{$this->catId}", 'class' => $className, 'name' => $elem->name, $html_options ); # multiple options 'name' attribute should have array hint [] if ( $elem->attributes['multiple'] !== null ) { $select['multiple'] = 'multiple'; $select['name'] .= '[]'; } # determine visual height of select options list if ( ( $size = $elem->attributes['height'] ) !== 0 ) { if ( is_int( $size ) ) { if ( count( $elem->options ) < $size ) { $size = count( $elem->options ); } } else { /* 'auto' */ $size = count( $elem->options ); } $select['size'] = $size; } $this->cell[] = $select; $this->catId++; }
/** * @return string html representation of user vote for Special:Pollresults output */ function displayUserVote() { $ctrl = $this->ctrl; $output = $this->displayHeader(); $output .= "<div class=\"qpoll\">\n" . "<table class=\"qdata\">\n"; foreach ( $ctrl->ProposalText as $propkey => &$serialized_tokens ) { if ( !is_array( $dbtokens = unserialize( $serialized_tokens ) ) ) { throw new MWException( 'dbtokens is not an array in ' . __METHOD__ ); } $catId = 0; $row = array(); foreach ( $dbtokens as &$token ) { if ( is_string( $token ) ) { # add a proposal part $row[] = array( '__tag' => 'span', 'class' => 'prop_part', qp_Setup::entities( $token ) ); } elseif ( is_array( $token ) ) { # add a category definition with selected text answer (if any) # resulting category view tagarray $catview = array( '__tag' =>'span', 'class' => 'cat_part', '' // text_answer ); if ( array_key_exists( $propkey, $ctrl->ProposalCategoryId ) && ( $id_key = array_search( $catId, $ctrl->ProposalCategoryId[$propkey] ) ) !== false ) { if ( ( $text_answer = $ctrl->ProposalCategoryText[$propkey][$id_key] ) === '' ) { if ( count( $token ) === 1 ) { # indicate selected checkbox / radiobuttn $catview[0] = qp_Setup::RESULTS_CHECK_SIGN; } } else { # text answer is not empty; # try to extract select multiple, if any $text_answer = explode( qp_Setup::SELECT_MULTIPLE_VALUES_SEPARATOR, $text_answer ); # place unused categories into the value of 'title' attribute $titleAttr = ''; foreach ( $token as &$option ) { if ( !in_array( $option, $text_answer ) ) { if ( $titleAttr !== '' ) { $titleAttr .= ' | '; } $titleAttr .= qp_Setup::entities( $option ); } } if ( count( $text_answer ) > 1 ) { # selected multiple values; # re-create the view for multiple category parts $catview = array(); foreach ( $text_answer as $key => &$cat_part ) { $tag = array( '__tag' => 'span', 'class' => 'cat_part', 'title' => $titleAttr, qp_Setup::specialchars( $cat_part ) ); if ( in_array( $cat_part, $token ) ) { $tag['class'] .= ( $key % 2 === 0 ) ? ' cat_even' : ' cat_odd'; } else { # add 'cat_unanswered' CSS class only to select multiple values $tag['class'] .= ' cat_unanswered'; } if ( $key == 0 ) { $tag['class'] .= ' cat_first'; } $catview[] = $tag; } } else { # text input or textarea $catview['title'] = $titleAttr; # note that count( $text_answer) here cannot be zero, because # explode() was performed on non-empty $text_answer $catview[0] = qp_Setup::specialchars( array_pop( $text_answer ) ); } } } else { # many browsers trim the spaces between spans when the text node is empty; # use non-breaking space to prevent this $catview[0] = ' '; $catview['class'] .= ' cat_unanswered'; } $row[] = $catview; # move to the next category (if any) $catId++; } else { throw new MWException( 'DB token has invalid type (' . gettype( $token ) . ') in ' . __METHOD__ ); } } $output .= qp_Renderer::displayRow( array( $row ), array( 'class' => 'qdatatext' ) ); } $output .= "</table>\n" . "</div>\n"; return $output; }
/** * Builds the question with fully parsed headers * * internally, the header is split into * main header (part inside curly braces) and * body header (categories and metacategories defitions) * * @param $header : the text of question "main" header (common question and XML-like attrs) * @param $body : the text of question body * for tabular questions body begins with header line that defines * categories and spans, followed by proposal lines) * @return question object with parsed headers */ function parseQuestionHeader( $header, $body ) { # parse questions common question and XML attributes $question = $this->parseMainHeader( $header ); if ( $question->getState() != 'error' ) { # load previous user choice, when it's available and DB header is compatible with parsed header if ( !method_exists( $question, 'parseBody' ) ) { $question->setState( 'error', wfMsgHtml( 'qp_error_question_not_implemented', qp_Setup::entities( $question->mType ) ) ); } elseif ( $body === '' ) { $question->setState( 'error', wfMsgHtml( 'qp_error_question_empty_body' ) ); } else { # build $question->raws[] $question->splitRawProposals( $body ); # parse the categories and spans (metacategories) $question->parseBodyHeader( $body ); } } return $question; }
function formatResult( $result ) { global $wgLang, $wgContLang; $link = ""; if ( $result !== null ) { $uid = intval( $result->uid ); $userName = $result->username; $userTitle = Title::makeTitleSafe( NS_USER, $userName ); $user_link = $this->qpLink( $userTitle, $userName ); $voice_link = $this->qpLink( $this->getTitle(), wfMsg( 'qp_voice_link' . ( $this->inverse ? "_inv" : "" ) ), array(), array( "id" => intval( $this->pid ), "uid" => $uid, "action" => "uvote" ) ); $text_answer = ( $result->text_answer == '' ) ? '' : '<i>' . qp_Setup::entities( $result->text_answer ) . '</i>'; $link = wfMsg( 'qp_results_line_qucl', $user_link, $voice_link, $text_answer ); } return $link; }