コード例 #1
0
function pyBoxHead()
{
    echo "<script type='text/javascript'>\n";
    printJSTranslation();
    echo sprintf("var SUBMITURL = '%s';\n", USUBMIT);
    echo sprintf("var SETCOMPLETEDURL = '%s';\n", USETCOMPLETED);
    echo sprintf("var CONSOLEURL = '%s';\n", cscurl('console'));
    echo sprintf("var FILESURL = '%s';\n", UFILES);
    echo sprintf("var HISTORYURL = '%s';\n", UHISTORY);
    echo sprintf("var VISUALIZEURL = '%s';\n", cscurl('visualize'));
    echo sprintf("var MESSAGEURL = '%s';\n", UMESSAGE);
    echo sprintf("var MAILURL = '%s';\n", cscurl('mail'));
    echo sprintf("var DEFAULTTIMEOUTMS = '%s';\n", (WALLFACTOR * 1 + WALLBUFFER) * 1000);
    echo sprintf("var PB_LANG4 = '%s';\n", currLang4());
    echo "</script>\n";
    echo '<link type="text/css" rel="stylesheet" href="' . UPYBOXCSS . '" />' . "\n";
    echo '<script type="text/javascript" src="' . UPYBOXJS . '"></script>' . "\n";
    echo "<link rel='stylesheet' type='text/css' href='" . UPYBOX . "customizations-codemirror/codemirror-specific.css'>\n";
    // variant of codemirror.css
    echo "<link rel='stylesheet' type='text/css' href='" . UPYBOX . "customizations-codemirror/codemirror-extras.css'>\n";
    // added styling
    echo "<link rel='stylesheet' type='text/css' href='" . UPYBOX . "customizations-codemirror/textmate.css'>\n";
    // theme
    echo "<script type='text/javascript' src='" . UCODEMIRROR3 . "lib/codemirror.js'></script>\n";
    echo "<script type='text/javascript' src='" . UCODEMIRROR3 . "mode/python/python.js'></script>\n";
    echo "<script type='text/javascript' src='" . UFLEXIGRID . "js/flexigrid.js'></script>\n";
    echo '<link type="text/css" rel="stylesheet" href="' . UFLEXIGRID . 'css/flexigrid.css" />' . "\n";
    if (stripos($_SERVER["HTTP_USER_AGENT"], 'MSIE') !== FALSE) {
        echo '<style type="text/css"> li.pyscrambleLI {height: 26px;} </style>' . "\n";
    }
    if (stripos($_SERVER["HTTP_USER_AGENT"], 'FIREFOX') !== FALSE) {
        echo '<style type="text/css"> .pybox textarea {white-space: nowrap;} </style>' . "\n";
    }
    global $pyRenderCount;
    $pyRenderCount = 0;
    global $popupBoxen;
    $popupBoxen = "";
}
コード例 #2
0
function niceFlex($id, $title, $fileSuffix, $functionName, $dbparams)
{
    include_once "db-{$fileSuffix}.php";
    $dbparams["lang"] = currLang4();
    $url = UDBPREFIX . $fileSuffix . ".php";
    $query_result = call_user_func($functionName, " limit 0,0", '', '', $dbparams);
    if (is_string($query_result)) {
        $rows = __t("n/a");
    } else {
        $rows = $query_result['total'];
    }
    return "<div class='collapseContain hiding' id='cc{$id}'>\n<div class='collapseHead' id='ch{$id}'><span class='icon'></span>{$title} ({$rows})</div>\n<div class='collapseBody' id='cb{$id}'></div></div>\n<script type='text/javascript'>\njQuery('#ch{$id}').click(function(e) {\n  if (0==jQuery('#cb{$id} .flexigrid').size()) pyflex({'id':'cb{$id}', 'url':'{$url}', 'dbparams':" . json_encode($dbparams) . "});\n});\n</script>";
}
コード例 #3
0
function pyBoxHandler($options, $content)
{
    //echo "PB[[[".$content."]]]";
    // given a shortcode, print out the html for the user,
    // and save the relevant grader options in a hash file.
    $id = generateId();
    if ($options == FALSE) {
        $options = array();
    }
    // wordpress does a weird thing where valueless
    for ($i = 0; array_key_exists($i, $options); $i++) {
        // attributes map like [0]=>'attname'.
        $options[$options[$i]] = "Y";
        // these lines change it to
        unset($options[$i]);
        // 'attname'=>'Y'
    }
    $shortcodeOptions = json_encode($options);
    // this will be put into DB.
    /// do some cleaning-up and preprocessing of options, and create the problem info for grader
    if (array_key_exists('translate', $options)) {
        $GLOBALS['pb_translation'] = $options['translate'];
    }
    if (array_key_exists('pyexample', $options)) {
        setSoft($options, 'grader', '*nograder*');
        setSoft($options, 'readonly', 'Y');
        setSoft($options, 'hideemptyinput', 'Y');
        unset($options['pyexample']);
    }
    if (array_key_exists('code', $options)) {
        // sugar: code is an alias for defaultcode
        $options["defaultcode"] = $options["code"];
        unset($options['code']);
    }
    $richreadonly = array_key_exists('richreadonly', $options);
    // sugar
    if ($richreadonly) {
        $options['readonly'] = "Y";
        unset($options['richreadonly']);
    }
    if (array_key_exists('nograder', $options)) {
        // syntactic sugar for nograder option
        if (array_key_exists('grader', $options)) {
            pyboxlog('Warning: grader overwritten with *nograder*');
        }
        $options["grader"] = "*nograder*";
        unset($options['nograder']);
    }
    foreach ($options as $optname => $optvalue) {
        // syntactic sugar for inplace grader
        if (preg_match('|tests|', $optname) > 0 || preg_match('|precode|', $optname) > 0) {
            $options["inplace"] = "Y";
        }
    }
    global $post, $lesson_reg_info;
    // $lessonNumber is numeric (major) part of lesson number
    // if lesson_reg_info is set we don't really care about displaying the pybox,
    // but we'll do things for consistency anyway. NB: when displaying a problem
    // in a place other than its original page (e.g., mail) this needs ot be fixed
    $post_title = isset($lesson_reg_info) ? get_the_title($lesson_reg_info['id']) : $post->post_name;
    if (preg_match('|^(\\d+).*|', $post_title, $matches) == 0) {
        $lessonNumber = -1;
    } else {
        $lessonNumber = $matches[1];
    }
    $inplace = booleanize(getSoft($options, 'inplace', 'N'));
    $scramble = booleanize(getSoft($options, 'scramble', 'N'));
    // important booleans used to determine
    $readonly = booleanize(getSoft($options, 'readonly', 'N'));
    // other options... get them first
    $showEditorToggle = booleanize(getSoft($options, 'showeditortoggle', 'N'));
    unset($options['scramble']);
    unset($options['readonly']);
    // don't extract() these!
    unset($options['inplace']);
    if ($inplace) {
        setSoft($options, 'hideemptyoutput', 'Y');
    }
    $defaultValues = array('defaultcode' => FALSE, 'autocommentline' => $lessonNumber > 3 && !($scramble || $readonly), 'console' => 'N', 'rows' => 10, 'allowinput' => $lessonNumber > 5 && !$scramble && !$readonly, 'disablericheditor' => ($lessonNumber > -1 && $lessonNumber < 7 || $scramble || $readonly) && !$richreadonly, 'usertni' => $inplace);
    foreach ($defaultValues as $key => $value) {
        if (!array_key_exists($key, $options)) {
            $options[$key] = $defaultValues[$key];
        }
    }
    extract($options);
    $allowinput = booleanize($allowinput);
    $disablericheditor = booleanize($disablericheditor);
    $console = booleanize($console);
    $autocommentline = booleanize($autocommentline);
    $usertni = booleanize($usertni);
    $facultative = isset($grader) && $grader == '*nograder*' || $console || $readonly;
    if ($scramble || $readonly) {
        $options['nolog'] = 'Y';
    }
    // for grader. note that if they are absent, their default values are 'N'
    if ($facultative) {
        $options['facultative'] = 'Y';
    } else {
        unset($options['facultative']);
    }
    if ($allowinput) {
        $options['allowinput'] = 'Y';
    } else {
        unset($options['allowinput']);
    }
    if ($scramble) {
        $options['scramble'] = 'Y';
    }
    // already unset
    if ($readonly) {
        $options['readonly'] = 'Y';
    }
    if ($inplace) {
        $options['inplace'] = 'Y';
    }
    if ($usertni) {
        $options['usertni'] = 'Y';
    } else {
        unset($options['usertni']);
    }
    $cosmeticOptions = array('defaultcode', 'autocommentline', 'console', 'rows', 'disablericheditor', 'scramble', 'readonly', 'showeditortoggle', 'title', 'placeholder');
    $copyForGrader = array();
    foreach ($options as $optname => $optvalue) {
        if (!in_array($optname, $cosmeticOptions)) {
            $copyForGrader[$optname] = $optvalue;
        }
    }
    if (array_key_exists('maxeditdistance', $options)) {
        $copyForGrader['originalcode'] = $defaultcode;
    }
    $optionsJson = json_encode($copyForGrader);
    $hash = md5($shortcodeOptions . $optionsJson);
    $slug = getSoft($options, 'slug', 'NULL');
    registerPybox($id, $slug, $scramble ? "scramble" : "code", $facultative, getSoft($options, 'title', NULL), $content, $shortcodeOptions, $hash, $optionsJson);
    if (isMakingDatabases()) {
        $res = do_short_and_sweetcode($content);
        // faster db generation with accurate count
        $GLOBALS['pb_translation'] = NULL;
        return $res;
    }
    /// we've delivered options to the grader. get on with producing html
    if ($defaultcode === FALSE && $scramble && $solver !== FALSE) {
        $lines = explode("\n", trim(softSafeDereference($solver)));
        shuffle($lines);
        $defaultcode = implode("\n", $lines);
    }
    if ($defaultcode !== FALSE) {
        try {
            $defaultcode = softSafeDereference($defaultcode);
        } catch (PyboxException $e) {
            $GLOBALS['pb_translation'] = NULL;
            return pberror("PyBox error: defaultcode file " . $defaultcode . " not found.");
        }
        $defaultcode = ensureNewlineTerminated($defaultcode);
    }
    /// actually start outputting here. part 1: headers and description
    $r = '';
    $readyScripts = '';
    $r .= '<form class="pbform" action="#" id="pbform' . $id . '" method="POST">' . "\n";
    if ($scramble) {
        $c = "scramble";
    } else {
        if (debugEnabled()) {
            $c = "debug";
        } else {
            $c = "";
        }
    }
    if ($facultative) {
        $c .= " facultative";
    }
    $r .= "<div class='pybox modeNeutral {$c}' id='pybox{$id}'>\n";
    if (!$facultative && !array_key_exists("slug", $options)) {
        pyboxlog("Hash " . $hash . " not read-only, but needs a slug", TRUE);
        $r .= slugwarn();
    }
    if ($facultative) {
        if ($console) {
            unset($options["title"]);
            $r .= heading("Console", $options);
        } else {
            $r .= heading(__t('Example'), $options);
        }
    } else {
        $r .= checkbox($slug);
        $r .= heading($scramble ? __t('Scramble Exercise') : __t('Coding Exercise'), $options);
        //if ($scramble)
        //  $r .= "<b>Note (Dec 13)</b>: scramble exercises are temporarily broken &mdash; sorry!<br>";
    }
    $r .= do_short_and_sweetcode($content);
    //instructions, problem description. process any shortcodes inside.
    // part 1.5: help box
    if (!$facultative && !$scramble) {
        $r .= '<div class="helpOuter" style="display: none;"><div class="helpInner">';
        if (!is_user_logged_in()) {
            $r .= '<div style="text-align: center">' . __t('You need to create an account and log in to ask a question.') . '</div>';
        } else {
            global $wpdb;
            $guru_login = get_the_author_meta('pbguru', get_current_user_id());
            if ($guru_login != '') {
                $guruid = $wpdb->get_var($wpdb->prepare('SELECT ID from ' . $wpdb->prefix . 'users WHERE user_login = %s', $guru_login));
            }
            $r .= '<div style="text-align: center">';
            if ($guru_login != '' and $guruid !== NULL) {
                $r .= __t('Send a question by e-mail to: ');
                $r .= "<select class='recipient'>\n<option value='1'>" . __t("My guru") . " ({$guru_login})</option>\n<option value='-1'>" . __t("CS Circles Assistant") . "</option>\n</select></div>";
            } else {
                $r .= __t('Send a question by e-mail to: ');
                $r .= "<select class='recipient'>\n<option value='-1'>" . __t("CS Circles Assistant") . "</option>\n<option value='0'>" . __t("(No guru specified in your profile)") . "</option>\n</select>";
                $r .= '<br/></div>';
            }
            $r .= __t("Enter text for the message below. <i>Be sure to explain where you're stuck and what you've tried so far. Your partial solution code will be automatically included with the message.</i>");
            $r .= "<textarea style='font-family: serif'></textarea>";
            $r .= "<table class='helpControls'><tr class='wp-core-ui'><td style='width: 50%'><a class='button' onclick='sendMessage({$id},\"{$slug}\")'>" . __t("Send this message") . "</a></td><td style='width: 50%'>\n           <a class='button' onclick='helpClick({$id})'>" . __t("Cancel") . "</a></td></tr></table>";
        }
        $r .= '</div></div>';
    }
    /// part 2: code input
    if ($readonly) {
        $thecode = trim($defaultcode);
        $rows = count(explode("\n", $thecode));
    } elseif ($console == "Y" && array_key_exists("consolecode", $_GET)) {
        $thecode = htmlspecialchars(html_entity_decode(stripslashes($_GET["consolecode"])));
        $rows = count(explode("\n", $thecode)) + 1;
    } else {
        $thecode = $defaultcode;
        if ($autocommentline) {
            $thecode .= __t('# delete this comment and enter your code here') . "\n";
        }
        if (array_key_exists('slug', $options) && $scramble === FALSE) {
            $savedCode = loadMostRecent($options['slug']);
            if ($savedCode !== NULL) {
                $thecode = $savedCode;
            }
        }
    }
    if ($scramble) {
        $r .= '<ul class="pyscramble" name="pyscramble" id="pyscramble' . $id . '">' . "\n";
        foreach (explode("\n", rtrim($thecode)) as $s) {
            if (strpos($s, 'delete this comment') === FALSE) {
                // fix an old bug -- got stuck in database
                $r .= ' <li class="pyscramble">' . (trim($s) == '' ? '&nbsp;' : htmlspecialchars(html_entity_decode($s))) . "</li>\n";
            }
        }
        $r .= "</ul>\n";
        $r .= "<input type='hidden' id='usercode{$id}' name='usercode{$id}'/>\n";
    } else {
        //    $r .= "<div class='acecontain ace_hide' id='acecontain$id' ><div class='aceinner' id='ace$id'></div></div>";
        $px = $rows * 26 + 6;
        //+6 for border, padding in weird box model
        $h = $px;
        if (!$readonly) {
            $h = max(50, $h);
        }
        $h = " style='height: {$h}px;'";
        $ro = $readonly ? "readonly='readonly'" : "";
        $c = $readonly ? "RO" : "RW";
        $p = $readonly ? " style = 'height : {$px}px;' " : "";
        $s = $readonly ? "" : "resizy";
        //cols=... required for valid html but width actually set by css
        //height is set explicitly since it's the only way for IE to render the textarea at the correct height
        $pl = array_key_exists("placeholder", $options) ? "placeholder='" . $options['placeholder'] . "'" : "";
        $r .= "<div class='pyboxTextwrap pyboxCodewrap {$c} {$s}' {$h}><textarea wrap='off' name='usercode{$id}' id='usercode{$id}' {$pl} cols=10 rows={$rows} {$ro} {$p} class='pyboxCode {$c}'>\n";
        $r .= $thecode;
        $r .= '</textarea></div>' . "\n";
    }
    // part 2.5 history container
    $r .= "<div id='pbhistory{$id}' class='flexcontain' style='display:none;'></div>\n";
    /// part 3: stdin
    if ($allowinput) {
        if ($usertni === TRUE) {
            $description = __t('Enter testing statements like <tt>print(myfunction("test argument"))</tt> below.');
        } else {
            $description = __t("You may enter input for the program in the box below.");
        }
        $r .= '<div name="pyinput" id="pyinput' . $id . '">';
        $r .= $description;
        $r .= '<div class="pyboxTextwrap resizy" style="height: 102px;" ><textarea wrap="off" name="userinput" class="pyboxInput" cols=10 rows=4></textarea></div>';
        $r .= '</div>' . "\n";
        //cols=10 required for valid html but width actually set by css
    }
    /// part 4: controls
    $tni = $usertni ? 'Y' : 'N';
    $actions = array();
    if ($allowinput) {
        $actions['switch'] = array('id' => "switch{$id}", 'value' => 'Input Switch', 'onclick' => "pbInputSwitch({$id},'{$tni}')");
    }
    if (!$disablericheditor) {
        //    $userLikesRich = (!is_user_logged_in()) || ("true"!==get_the_author_meta( 'pbplain', get_current_user_id()));
        $userLikesRich = TRUE;
        if ($showEditorToggle || $richreadonly) {
            $actions['CMtoggle'] = array('value' => __t('Rich editor'), 'id' => "toggleCM{$id}", 'onclick' => "pbToggleCodeMirror({$id})");
        }
        if ($userLikesRich) {
            $readyScripts .= "jQuery(function(){pbToggleCodeMirror({$id});});";
        }
    }
    if (!$scramble && !$console && ($lessonNumber >= 4 || $lessonNumber < 0)) {
        $actions['consolecopy'] = array('value' => __t('Open in console'), 'onclick' => "pbConsoleCopy({$id})");
    }
    if (!$scramble && ($lessonNumber >= 4 || $lessonNumber < 0)) {
        $actions['visualize'] = array('value' => __t('Visualize'), 'onclick' => "pbVisualize({$id},'{$tni}')");
    }
    if (!$readonly && !$scramble) {
        //$actions['save'] = array('value'=>'Save without running', 'onclick'=>"pbSave($id)");
        if (array_key_exists("slug", $options)) {
            $historyAction = "historyClick({$id},'{$slug}')";
            $actions['history'] = array('value' => __t('History'), 'onclick' => $historyAction);
        }
        if (!($readonly === "Y") && $defaultcode != '' && $defaultcode !== FALSE) {
            // prepare the string for javaScript enclosure
            // we put in single-quotes, rather than json's default double quotes, for compatibility with
            // our $button usage
            $dc = substr(json_encode(htmlspecialchars_decode($defaultcode, ENT_QUOTES), JSON_HEX_APOS), 1, -1);
            $r .= "<input type='hidden' id='defaultCode{$id}' value='{$dc}'></input>\n";
            $actions['default'] = array('value' => __t('Reset code to default'), 'onclick' => "pbSetText({$id},descape(\$('#defaultCode{$id}').val()))");
        }
    }
    if (!$facultative && !$scramble && !get_option('cscircles_hide_help')) {
        $actions['help'] = array('value' => __t('Help'), 'onclick' => "helpClick({$id});");
    }
    if ($richreadonly) {
        $actions = array('CMtoggle' => $actions['CMtoggle']);
    }
    // get rid of all other options
    $r .= "<div class='pyboxbuttons'><table><tr>\n";
    if (!$richreadonly) {
        $r .= "<td><input type='submit' name='submit' id='submit{$id}' value=' '/></td>\n";
    }
    $mb = 3;
    //maximum number of buttons, not counting 'submit'
    $i = 0;
    foreach ($actions as $name => $atts) {
        $i++;
        if ($i <= $mb) {
            $r .= button($name, $atts);
            continue;
        }
        if ($i == 1 + $mb) {
            $r .= "</tr></table><select id='pbSelect{$id}' class='selectmore'><option name='more'>" . __t("More actions...") . "</option>\n";
        }
        $r .= option($name, $atts);
    }
    if (count($actions) > $mb) {
        $r .= "</select></div>\n";
    } else {
        $r .= "</tr></table></div>\n";
    }
    if (isset($cpulimit) && $cpulimit != 1) {
        $timeout = (WALLFACTOR * $cpulimit + WALLBUFFER + 2) * 1000;
        // + 2 seconds for network latency each way
        $r .= "<input type='hidden' name='timeout' value='{$timeout}'/>\n";
    }
    $r .= '<input type="hidden" name="lang" value="' . currLang4() . '"/>';
    $r .= '<input type="hidden" id="inputInUse' . $id . '" name="inputInUse" value="Y"/>' . "\n";
    $r .= '<input type="hidden" name="pyId" value="' . $id . '"/>' . "\n";
    $r .= '<input type="hidden" name="hash" value="' . $hash . '"/>' . "\n";
    // although inputInUse starts as Y, the next script sets it to N and fixes the button labels
    $readyScripts .= $allowinput ? 'pbInputSwitch(' . $id . ',"' . ($usertni ? 'Y' : 'N') . '");' : 'document.getElementById("submit' . $id . '").value = "' . __t('Run program') . '";' . 'document.getElementById("inputInUse' . $id . '").value = "N";';
    /// part 5 : results area, and footers
    $c = count($actions) > $mb ? ' avoidline' : '';
    $r .= "<div id='pbresults{$id}' class='pbresults{$c}'></div>\n";
    $r .= problemSourceWidget(array('hash' => $hash), count($actions) > $mb);
    $r .= '</div>' . "\n";
    $r .= '</form>' . "\n";
    if ($readyScripts != '') {
        $r .= "<script type='text/javascript'>{$readyScripts}</script>\n";
    }
    $GLOBALS['pb_translation'] = NULL;
    return $r;
}