public static function newFromUrl($url, $langCode, $dbType)
 {
     $url = str_replace('http://www.wikihow.com/', '', $url);
     $pageTitle = Misc::getUrlDecodedData($url);
     $row = self::getDBRowFromPageTitle($pageTitle, $langCode, $dbType);
     return is_null($row) ? null : BabelfishArticle::newFromDBRow($row, $dbType);
 }
Beispiel #2
0
 public function processUrlListByLang(&$urlList, $langCode)
 {
     $excludedKey = $this->getWAPConfig()->getExludedArticlesKeyName();
     $excludeList = explode("\n", ConfigStorage::dbGetConfig($excludedKey));
     $urlList = Misc::getUrlDecodedData($urlList);
     $processedUrls = array(WAPArticle::STATE_INVALID => array(), WAPArticle::STATE_EXCLUDED => array(), WAPArticle::STATE_UNASSIGNED => array(), WAPArticle::STATE_ASSIGNED => array(), WAPArticle::STATE_COMPLETED => array(), WAPArticle::STATE_NEW => array());
     $urls = $this->parseURLlist($urlList, $langCode);
     foreach ($urls as $url) {
         // If it's in the system, put it in the right bucket
         $wa = $url['a'];
         if ($wa->exists()) {
             $url['aid'] = $aid = $wa->getArticleId();
             if (in_array($aid, $excludeList)) {
                 $processedUrls[WAPArticle::STATE_EXCLUDED][] = $url;
             } elseif ($wa->isCompleted()) {
                 $processedUrls[WAPArticle::STATE_COMPLETED][] = $url;
             } elseif ($wa->isAssigned()) {
                 $processedUrls[WAPArticle::STATE_ASSIGNED][] = $url;
             } elseif (!$wa->isAssigned()) {
                 $processedUrls[WAPArticle::STATE_UNASSIGNED][] = $url;
             } else {
                 throw new Exception("Bad url: {$url['url']} {$url['lang']}. Report to your trusty wikiHow engineer.");
             }
         } else {
             // If it's not in the system, see if it's even a valid title (exists and isn't a redirect)
             // If it is then check to see if it's excluded.
             // If it isn't excluded then it's considered a new article
             $page = Misc::getPagesFromURLs(array($url['url']), array('page_id', 'page_is_redirect'), true);
             $page = reset($page);
             if (!empty($page) && $page['page_is_redirect'] != 1) {
                 $aid = $page['page_id'];
                 $url['aid'] = $aid;
                 if (in_array($aid, $excludeList)) {
                     $processedUrls[WAPArticle::STATE_EXCLUDED][] = $url;
                 } else {
                     $processedUrls[WAPArticle::STATE_NEW][] = $url;
                 }
             } else {
                 $processedUrls[WAPArticle::STATE_INVALID][] = $url;
             }
         }
     }
     return $processedUrls;
 }
 function buildSQL(&$ids)
 {
     global $wgRequest;
     $sql = Misc::getUrlDecodedData($wgRequest->getVal('sql'), false);
     if (stripos($sql, "FROM titus") > 0) {
         // Always get the language_code
         if (stripos($sql, "ti_language_code") == FALSE) {
             $sql = str_replace("FROM titus", ', ti_language_code as "ti_language_code" FROM titus', $sql);
         }
         $sql = str_replace("FROM titus", "FROM " . TitusDB::TITUS_TABLE_NAME, $sql);
         //Hack to include ti_page_id and ti_language_code
         if (!preg_match('@SELECT\\ +\\*@i', $sql) && !preg_match('@ti_page_id as "ti_page_id"@', $sql)) {
             $sql = preg_replace('@SELECT @', 'SELECT ti_page_id as "ti_page_id",', $sql);
         }
     } else {
         $sql = "SELECT * FROM " . TitusDB::TITUS_TABLE_NAME;
     }
     $pageCondition = "";
     if ($this->language != "") {
         $pageCondition = " ti_language_code='" . mysql_escape_string($this->language) . "'";
     }
     $langConditions = array();
     if (is_array($ids) && sizeof($ids) > 0) {
         $sz = sizeof($ids);
         foreach ($ids as $id) {
             if (!empty($id['page_id'])) {
                 if (!isset($langConditions[$id['language']])) {
                     $langConditions[$id['language']] = array();
                 }
                 $langConditions[$id['language']][] = $id['page_id'];
             }
             #$pageCondition .= "(ti_page_id ='" . $id['page_id'] . "' AND ti_language_code='" . $id['language'] ."')";
         }
         foreach ($langConditions as $lang => $langIds) {
             if ($pageCondition != "") {
                 $pageCondition .= " OR ";
             }
             $pageCondition .= "(ti_language_code='" . $lang . "' AND ti_page_id in (" . implode(",", $langIds) . "))";
         }
     }
     if (stripos($sql, "WHERE ")) {
         if ($pageCondition) {
             $pageCondition = " AND (" . $pageCondition . ")";
         }
         $sql = preg_replace("@WHERE (.+)\$@", "WHERE (\\1) {$pageCondition}", $sql);
     } elseif ($pageCondition != "") {
         $sql .= " WHERE {$pageCondition} {$orderBy}";
     } else {
         $sql .= " {$orderBy}";
     }
     return $sql;
 }
Beispiel #4
0
 /**
  * Add a bunch of URLs to the database for adding their images to various languages
  * @param urls New-line seperated list of URLs or Article ids from POST
  * @param langs Comma-seperated list of languages to add the images on
  */
 private function addImages($urls, $langs)
 {
     $urls = preg_split("@[\r\n]+@", Misc::getUrlDecodedData($urls));
     $langs = preg_split("@,@", urldecode($langs));
     $realUrls = array();
     $langIds = array();
     foreach ($urls as $url) {
         if (is_numeric($url)) {
             $langIds[] = array("lang" => "en", "id" => $url);
         } else {
             $realUrls[] = $url;
         }
     }
     $pagesA = Misc::getPagesFromURLs($realUrls, array('page_id', 'page_title'));
     $badURLs = array();
     $results = array();
     foreach ($realUrls as $url) {
         if (!isset($pagesA[$url])) {
             foreach ($langs as $lang) {
                 ImageTransfer::addBadURL($url, $lang, "URL not found");
             }
             $results[] = array('fromURL' => $url, 'toURL' => '', 'status' => 'Bad URL');
         }
     }
     $pagesB = Misc::getPagesFromLangIds($langIds, array('page_id', 'page_title'));
     $pages = array_merge($pagesA, $pagesB);
     $fromIDs = array();
     $urlLookup = array();
     foreach ($pages as $page) {
         $fromIDs[] = $page['page_id'];
         $urlLookup[$page['page_id']] = Misc::getLangBaseURL('en') . '/' . $page['page_title'];
     }
     if (sizeof($fromIDs) == 0) {
         return array();
     }
     // Fetch to cache the pages for later use in addImage
     $this->batchFetchPages("en", $fromIDs);
     $langTLs = array();
     foreach ($langs as $lang) {
         $langTLs[$lang] = TranslationLink::getLinks("en", $lang, array("tl_from_aid in (" . implode(',', $fromIDs) . ")"));
         $newFromIds = array_map(function ($m) {
             return $m->fromAID;
         }, $langTLs[$lang]);
         foreach ($fromIDs as $id) {
             //Add error links
             if (!in_array($id, $newFromIds)) {
                 $this->addImage($id, $lang, 0);
                 if (isset($urlLookup[$id])) {
                     $results[] = array('fromURL' => $urlLookup[$id], 'toURL' => '', 'status' => 'Could not find any translation link to ' . $lang);
                 }
             }
         }
         TranslationLink::batchPopulateURLs($langTLs[$lang]);
         // Cache the other language pages too in a batch
         $langIds = array();
         foreach ($langTLs[$lang] as $tl) {
             $langIds[] = $tls->toAID;
         }
         $this->batchFetchPages($lang, $langIds);
     }
     foreach ($langs as $lang) {
         foreach ($langTLs[$lang] as $tl) {
             if (!$this->addImage($tl->fromAID, $tl->toLang, $tl->toAID)) {
                 $results[] = array('fromURL' => $tl->fromURL, 'toURL' => $tl->toURL, 'status' => 'Queued');
             } else {
                 $results[] = array('fromURL' => $tl->fromURL, 'toURL' => $tl->toURL, 'status' => 'Failed to queue');
             }
         }
     }
     return $results;
 }
 function articleDetails()
 {
     global $wgRequest, $wgOut;
     $url = Misc::getUrlDecodedData($wgRequest->getVal('url'));
     $msg = "";
     try {
         $langCode = $this->cu->getLanguageTag();
         // throws exception if no language tag set for user
         $processedUrls = $this->wapDB->processUrlListByLang($url, $langCode);
         $articleState = 'invalid';
         $articleClass = $this->config->getArticleClassName();
         $ca = $articleClass::newFromUrl($url, $langCode, $this->dbType);
         foreach ($processedUrls as $state => $urls) {
             if (!empty($urls)) {
                 $articleState = $state;
                 break;
             }
         }
         $msg = "Not a valid wikiHow Article.";
         $supportEmail = $this->config->getSupportEmailAddress();
         switch ($articleState) {
             case 'completed':
                 $msg = $this->cu->getId() == $ca->getUserId() ? " You have already completed this article" : "This article is already completed.";
                 break;
             case 'assigned':
                 $msg = $this->cu->getId() == $ca->getUserId() ? "You have already reserved this article." : "This article is reserved by another user.";
                 break;
             case 'excluded':
                 $msg = "This article is on the exclude list. It is permanently unavailable.";
                 break;
             case 'unassigned':
                 $t = Title::newFromId($urls[0]['aid']);
                 if (!$t || !$t->exists()) {
                     // Make sure it's still a valid wikiHow title. Edge case where articles are deleted
                     // before nightly maintenance script cleans those up
                     // If it isn't, stick with the default message
                 } else {
                     if (!$this->cu->canView($ca)) {
                         $msg = "This article is on a special list, please email {$supportEmail} for permission to reserve.";
                     } else {
                         // Show the article
                         $vars = $this->getDefaultVars();
                         $vars['a'] = $ca;
                         $vars['cu'] = $this->cu;
                         $tmpl = new WAPTemplate($this->dbType);
                         $msg = $tmpl->getHtml('article_details.tmpl.php', $vars);
                     }
                 }
                 break;
             case 'new':
                 $msg = $this->config->getNewArticleMessage($supportEmail);
                 break;
             case 'invalid':
                 // Stick with the default message
                 break;
         }
     } catch (Exception $e) {
         $msg = "No language tag set.  Please contact " . $this->config->getSupportEmailAddress();
     }
     $msg = "<h4>{$msg}</h4>";
     $wgOut->setArticleBodyOnly(true);
     $wgOut->addHtml($msg);
 }
 function articleDetails()
 {
     global $wgRequest, $wgOut;
     $wgOut->setArticleBodyOnly(true);
     $vars = $this->getDefaultVars($this->dbType);
     $articleClass = $this->config->getArticleClassName();
     $url = Misc::getUrlDecodedData($wgRequest->getVal('url'));
     $langs = $this->config->getSupportedLanguages();
     foreach ($langs as $lang) {
         $ca = $articleClass::newFromUrl($url, $lang, $this->dbType);
         $vars['lang'] = $lang;
         $vars['article'] = $ca;
         $vars['user'] = $ca->getUser();
         $vars['tags'] = $ca->getTags();
         $tmpl = new WAPTemplate($this->dbType);
         $wgOut->addHtml($tmpl->getHtml('article_details_admin.tmpl.php', $vars));
         $wgOut->addHtml($html);
     }
 }
    /**
     * Execute special page.  Only available to wikihow staff.
     */
    public function execute()
    {
        global $wgRequest, $wgOut, $wgUser, $wgLang;
        $user = $wgUser->getName();
        $userGroups = $wgUser->getGroups();
        $extraUsers = array('Gersh');
        if ($wgUser->isBlocked() || !in_array('staff', $userGroups) && !in_array($user, $extraUsers)) {
            $wgOut->setRobotpolicy('noindex,nofollow');
            $wgOut->errorpage('nosuchspecialpage', 'nospecialpagetext');
            return;
        }
        if ($wgRequest->wasPosted()) {
            // handle more URLs at once
            ini_set('memory_limit', '512M');
            set_time_limit(0);
            ignore_user_abort(true);
            $wgOut->setArticleBodyOnly(true);
            $dbr = wfGetDB(DB_SLAVE);
            $action = $wgRequest->getVal('action', '');
            self::$discardThreshold = $wgRequest->getInt('discard-threshold', 0);
            $dataType = $wgRequest->getVal('data-type');
            $pageList = $wgRequest->getVal('pages-list', '');
            $domain = $wgRequest->getVal('domain', 'bt');
            $pageList = Misc::getUrlDecodedData($pageList);
            $urls = self::parseURLlist($pageList);
            if (empty($urls)) {
                $result = array('result' => '<i>ERROR: no URLs given</i><br/>');
                print json_encode($result);
                return;
            }
            if ('reset' == substr($action, 0, 5)) {
                if ('reset' == $action) {
                    // both www and mobile
                    foreach (self::$domains as $domain => $foo) {
                        $html .= self::resetStats($urls, $domain);
                    }
                } else {
                    // just one domain
                    $domain = substr($action, -2);
                    $html = self::resetStats($urls, $domain);
                }
                self::resetVarnishes($urls);
                self::mailUserResetDone($wgUser, $urls);
            } elseif ('fetch' == $action) {
                $html = '';
                if ($dataType == 'csv') {
                    self::outputCSV($urls);
                    return;
                } else {
                    foreach (self::$domains as $domain => $foo) {
                        $html .= self::fetchStats($urls, $domain);
                    }
                }
            } else {
                $html = 'ERROR: unknown action';
            }
            $result = array('result' => $html);
            print json_encode($result);
            return;
        }
        $wgOut->setHTMLTitle('Admin - Bounce Tests (Stu) - wikiHow');
        $defaultDiscardThreshold = self::$discardThreshold;
        $domain_opts = '';
        foreach (self::$domains as $domain => $label) {
            $domain_opts .= "<option value=\"{$domain}\">{$label}</option>\n";
        }
        $specialPage = $this->specialPage;
        $tmpl = <<<EOHTML
<script src="/extensions/wikihow/common/download.jQuery.js"></script>
<form id="admin-form" method="post" action="/Special:{$specialPage}">
<div style="font-size: 16px; letter-spacing: 2px; margin-bottom: 15px;">
\tFetch or Reset Bounce Timer (Stu) Stats
</div>
<div style="font-size: 13px; margin-bottom: 10px; border: 1px solid #dddddd; padding: 10px;">
\t<div>
\t\tViews discard threshold: <input id="discard-threshold" type="text" size="4" name="discard-threshold" value="{$defaultDiscardThreshold}" />
\t\t<!--
\t\t&nbsp;&nbsp;Domain
\t\t<select name="domain" id="pages-domains">
\t\t<option value="all">All</option>
\t\t{$domain_opts}
\t\t</select>
\t\t//-->
\t</div>
\t<div style="margin-top: 5px;">
\t\t<input type="radio" name="data-type" value="summary" checked> Summary</input>
\t\t<input type="radio" name="data-type" value="csv"> CSV</input>
\t</div>
</div>
<div style="font-size: 13px; margin: 20px 0 7px 0;">
\tEnter a list of URL(s) such as <code style="font-weight: bold;">http://www.wikihow.com/Lose-Weight-Fast</code> to which this tool will apply.  One per line.
</div>
<textarea id="pages-list" name="pages-list" type="text" rows="10" cols="70"></textarea><br/>
<button id="pages-fetch" disabled="disabled" style="padding: 5px;">fetch stats</button>
<button id="pages-resetbt" disabled="disabled" style="padding: 5px;">reset www</button>
<button id="pages-resetmb" disabled="disabled" style="padding: 5px;">reset mobile</button>
<button id="pages-reset" disabled="disabled" style="padding: 5px;">reset all</button>
<br/>
<br/>
<div id="pages-result">
</div>
</form>

<script>
(function(\$) {
\tfunction doServerAction(action) {
\t\tvar dataType = \$('input:radio[name=data-type]:checked').val();
\t\tvar url = '/Special:{$specialPage}/views.csv?action=' + action + '&data-type=' + dataType;
\t\tif ('summary' == dataType) {
\t\t\tvar form = \$('#admin-form').serializeArray();
\t\t\t\$('#pages-result').html('loading ...');
\t\t\tvar finished = false;
\t\t\t\$.post(url,
\t\t\t\tform,
\t\t\t\tfunction(data) {
\t\t\t\t\tfinished = true;
\t\t\t\t\t\$('#pages-result').html(data['result']);
\t\t\t\t\t\$('#pages-list').focus();
\t\t\t\t},
\t\t\t\t'json')
\t\t\t\t.complete(function () {
\t\t\t\t\tif (!finished) {
\t\t\t\t\t\t\$('#pages-result').html('Server call is taking too long. Wait for an email.');
\t\t\t\t\t}
\t\t\t\t});
\t\t} else { // csv
\t\t\tvar form = 'pages-list=' + encodeURIComponent(\$('#pages-list').val());
\t\t\t\$.download(url, form);
\t\t}
\t}

\t\$(document).ready(function() {
\t\t\$('#pages-resetbt, #pages-resetmb, #pages-reset, #pages-fetch')
\t\t\t.prop('disabled', false)
\t\t\t.click(function () {
\t\t\t\tvar action = \$(this).attr('id').replace(/^pages-/, '');
\t\t\t\tvar answer = true;
\t\t\t\tif ('reset' == action.substring(0,5)) {
\t\t\t\t\tvar count = \$('#pages-list').val().split(/\\n/).length;
\t\t\t\t\tvar domain = 'www';
\t\t\t\t\tif ('resetmb'==action) domain='mobile';
\t\t\t\t\telse if ('reset'==action) domain='all domains';
\t\t\t\t\tanswer = confirm('Are you sure you want to reset data for approx. ' + count + ' URL(s) on ' + domain + '?');
\t\t\t\t}
\t\t\t\tif (answer) {
\t\t\t\t\tdoServerAction(action);
\t\t\t\t}
\t\t\t\treturn false;
\t\t\t});
\t\t/*
\t\t\$('#pages-allcheck')
\t\t\t.click(function() {
\t\t\t\tif (\$(this).prop('checked')){
\t\t\t\t\t\$('#pages-reset').prop('disabled',false);
\t\t\t\t}else{
\t\t\t\t\t\$('#pages-reset').prop('disabled',true);
\t\t\t\t}
\t\t\t});
\t\t\$('#pages-domains')
\t\t\t.change(function(){
\t\t\t\tif (\$(this).attr('value')=='all'){
\t\t\t\t\t\$('#pages-reset').prop('disabled',true);
\t\t\t\t\t\$('#pages-allcheck').prop('disabled',false);
\t\t\t\t\t\$('#pages-check').css('color','');
\t\t\t\t}else{
\t\t\t\t\t\$('#pages-reset').prop('disabled',false);
\t\t\t\t\t\$('#pages-allcheck').prop('disabled',true).prop('checked',false);
\t\t\t\t\t\$('#pages-check').css('color','#ccc');
\t\t\t\t}
\t\t\t\t\$('#pages-result').html('');
\t\t\t});
\t\t*/

\t\t\$('#pages-list')
\t\t\t.focus();
\t});
})(jQuery);
</script>
EOHTML;
        $wgOut->addHTML($tmpl);
    }
 function outputArticleIdReport()
 {
     global $wgRequest;
     $ids = split("\n", trim(Misc::getUrlDecodedData($wgRequest->getVal('data'))));
     $dbr = wfGetDB(DB_SLAVE);
     $articles = array();
     foreach ($ids as $id) {
         $id = trim($id);
         $t = Title::newFromId($id);
         if ($t && $t->exists()) {
             $articles[] = array("id" => $id, "url" => $t->getFullUrl());
         }
     }
     if ($wgRequest->getVal('format') == 'csv') {
         $output = $this->getArticleIdReportCSV($articles);
         $this->sendFile('article_stats', $output);
     } else {
         $output = $this->getArticleIdReportHtml($articles);
         $this->sendHtml($output);
     }
 }
 function getQuery()
 {
     global $wgRequest;
     $days = $wgRequest->getVal('days');
     $userList = $wgRequest->getVal('users');
     $usersType = $wgRequest->getVal('usersType');
     $sql = Misc::getUrlDecodedData($wgRequest->getVal('sql'), false);
     if ($sql == "") {
         $sql = "select * from flavius_summary";
     }
     // We only get active users in the last 90 days
     if ($usersType == 'active') {
         $t = wfTimestamp(TS_MW, time() - 60 * 60 * 24 * 90);
         $ltSQL = "fe_last_touched > '" . $t . "'";
         if (preg_match("@where@i", $sql)) {
             $sql .= ' AND ' . $ltSQL;
         } else {
             $sql .= ' WHERE ' . $ltSQL;
         }
     } elseif ($usersType != 'all') {
         $users = preg_split("@[\r\n]+@", urldecode($userList));
         $ids = array();
         foreach ($users as $user) {
             if (preg_match("@http://www\\.wikihow\\.com/User:(.+)@i", $user, $matches)) {
                 $u = User::newFromName($matches[1]);
                 if ($u) {
                     $ids[] = $u->getId();
                 }
             }
         }
         if (sizeof($ids) > 0) {
             if (preg_match("@where@i", $sql)) {
                 $sql .= ' AND fe_user in ( ' . implode(',', $ids) . ')';
             } else {
                 $sql .= ' WHERE fe_user in (' . implode(',', $ids) . ')';
             }
         }
     }
     $rows = $this->getData($sql, $days);
     foreach ($rows as $row) {
         foreach ($row as $k => $v) {
             print "{$v} ";
         }
         print "\n";
     }
 }