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); }
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; }
/** * 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 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"; } }