protected function getOutput() { $this->setBlock(false); return '<a ' . $this->getClass() . ' ' . $this->getStyle() . ' href="' . $this->title->getOutput() . '">' . $this->caption->getOutput() . '</a>'; }
/** * check for plagiarism with copyscape * return true if there's an issue */ private static function copyCheck($t) { $threshold = 0.05; $result = ''; $r = Revision::newFromTitle($t); if (!$r) { return 'No such article'; } $text = Wikitext::flatten($r->getText()); $res = copyscape_api_text_search_internet($text, 'ISO-8859-1', 2); if ($res['count']) { $words = $res['querywords']; foreach ($res['result'] as $r) { if (!preg_match("@^http://[a-z0-9]*.(wikihow|whstatic|youtube).com@i", $r['url'])) { //if ($r['minwordsmatched'] / $words > $threshold) { //we got one! $result .= '<b>Plagiarized:</b> <a href="' . $r['url'] . '">' . $r['url'] . '</a><br />'; //} } } } else { $result = ''; } return $result; }
public static function getSelection($maxUrls, $minImages) { $output = array(); $dbr = wfGetDB(DB_SLAVE); $sql = 'SELECT pr_title FROM page_randomizer'; $rows = parent::loadRows($dbr, $sql, '', __METHOD__); shuffle($rows); foreach ($rows as $row) { $wikitext = ''; $steps = ''; $titleDBkey = $row['pr_title']; $title = Title::newFromDBkey($titleDBkey); if ($title) { $wikitext = parent::getWikitext($dbr, $title); } if ($wikitext) { list($steps, ) = Wikitext::getStepsSection($wikitext); } if ($steps) { $images = parent::getNumStepsImages($steps); if ($images >= $minImages) { $output[] = $title->getPartialURL(); if (count($output) >= $maxUrls) { break; } } } } return $output; }
/** * Resize the steps images in a list of Title objects. */ private static function enlargeImagesUrls(&$urls, $recenter, $px, $introPx) { foreach ($urls as &$url) { if (!$url['title']) { $err = 'Unable to load article'; $numImages = 0; } else { list($err, $numImages) = Wikitext::enlargeImages($url['title'], $recenter, $px, $introPx); } $url['err'] = $err; $url['images'] = $numImages; } }
/** * grab that wikitext */ private static function getWikitext($title) { $dbr = wfGetDB(DB_SLAVE); $wikitext = Wikitext::getWikitext($dbr, $title); $stepsText = ''; if ($wikitext) { list($stepsText, $sectionID) = Wikitext::getStepsSection($wikitext, true); //hack for illegal character if (strpos($wikitext, '‐')) { return array(); } } return array($wikitext, $stepsText, $sectionID); }
function synthesizeSummary($wikitext, $maxSteps, $fullURL) { $stepsSec = Wikitext::getStepsSection($wikitext, true); if (!$stepsSec) { return ''; } $stepsText = Wikitext::stripHeader($stepsSec[0]); if (Wikitext::countAltMethods($stepsText) > 0) { $altMethods = Wikitext::splitAltMethods($stepsText); foreach ($altMethods as $method) { if (Wikitext::isAltMethod($method) && Wikitext::countSteps($method) > 0) { $stepsText = $method; break; } } } $countSteps = Wikitext::countSteps($stepsText); $summaryOut = ''; $steps = Wikitext::splitSteps($stepsText); $count = 0; foreach ($steps as $step) { if (Wikitext::isStepSimple($step, false)) { $summary = Wikitext::summarizeStep($step); $summary = Wikitext::removeRefsFromFlattened($summary); if ($summary) { $count++; $break = $count > 1 ? "<br>" : ''; if ($count > $maxSteps) { $remaining = $countSteps - $maxSteps; $text = ''; if ($remaining >= 2) { $text = "{$remaining} more steps at wikiHow"; } elseif ($remaining == 1) { $text = "Another step at wikiHow"; } if ($text) { $href = htmlspecialchars($fullURL); $link = "<a href='{$href}'>{$text}</a>"; $summaryOut .= "{$break}{$link}"; } break; } else { $summaryOut .= "{$break}{$count}. {$summary}"; } } } } return $summaryOut; }
private function resizeImages($article) { global $wgServer; if (!$dbw) { $dbw = wfGetDB(DB_MASTER); } $err = ''; $title = Title::newFromURL($article); if (!$title || !$title->exists()) { return; } $wikitext = Wikitext::getWikitext($dbw, $title); if (!$wikitext) { $err = 'Unable to load wikitext'; } else { if (preg_match('@^#REDIRECT@m', $wikitext)) { $err = 'REDIRECT'; } else { list($stepsText, $sectionID) = Wikitext::getStepsSection($wikitext, true); list($stepsText, $err) = self::resizeEachImage($stepsText); if ($stepsText) { $wikitext = Wikitext::replaceStepsSection($wikitext, $sectionID, $stepsText, true); $comment = 'Resized images to the {{largeimage}} size.'; $err = Wikitext::saveWikitext($title, $wikitext, $comment); } } } if ($err) { $err .= chr(9) . $wgServer . '/' . $article; //print $err."\n"; self::logError($err); } elseif ($stepsText) { self::logIt($wgServer . '/' . $article); return $wgServer . '/' . $article; } }
function getDocData($row, $dbr, $printIntro = false) { $page_id = $row->page_id; $page_counter = $row->page_counter; $title = Title::newFromDBkey($row->page_title); if (!$title || !$title->exists()) { decho("unknown title for id", $page_id, false); return ""; } $wikitext = Wikitext::getWikitext($dbr, $title); $intro = Wikitext::getIntro($wikitext); //$intro = str_replace("{{toc}}", "", $intro); $intro = preg_replace('#\\{\\{.*?\\}\\}#s', '', $intro); $intro = trim(preg_replace('#\\[\\[.*?\\]\\]#s', '', $intro)); $intro = preg_replace('/\\s+/', ' ', trim($intro)); $intro = str_replace('<br>', '', $intro); //if (contains($intro, "Here's how:")) { if (stripos($intro, "here's how") !== FALSE || ":" == substr($intro, -1)) { //check the number of monthly page views... $data = getTitusData($row->page_id); if ($data->titus) { $ti30 = $data->titus->ti_30day_views; } if ($ti30 >= 5000 && $ti30 <= 6000) { echo $ti30 . " http://www.wikihow.com/" . $row->page_title . " "; if ($printIntro) { echo $intro; } echo "\n"; } } //echo $page_counter ." http://www.wikihow.com/".$row->page_title." ,> ".$intro."\n"; //echo "http://www.wikihow.com/".$row->page_title." ,> ".$intro."\n"; return $intro; }
private function keepMethod($methodId, $articleId, $altMethod, $altSteps) { global $wgUser, $wgParser; $title = Title::newFromID($articleId); if ($title) { $revision = Revision::newFromTitle($title); $article = new Article($title); if ($revision && $article) { $wikitext = $revision->getText(); $section = Wikitext::getStepsSection($wikitext, true); $newSection = $section[0] . "\n\n=== {$altMethod} ===\n{$altSteps}"; $newText = $wgParser->replaceSection($wikitext, $section[1], $newSection); $success = $article->doEdit($newText, MethodEditor::EDIT_COMMENT); if ($success) { $logPage = new LogPage('methedit', false); $altMethodTransform = str_replace(" ", "_", $altMethod); $logS = $logPage->addEntry("Added", $title, wfMsg('editor-approved-logentry', $title->getFullText(), $altMethod, $altMethodTransform)); $dbw = wfGetDB(DB_MASTER); $dbw->delete(MethodEditor::TABLE_NAME, array('ama_id' => $methodId)); } wfRunHooks("MethodEdited", array($wgUser, $title, '0')); return $success; } } }
/** * Check if two bits of wikitext have the same images * @param a First wiki-text to test * @param b Second wiki-text to test * @param altImageTags Array of alternative image regex to use such as imagen,... * @return True if the images are the same, and false otherwise */ public static function haveSameImages($a, $b, $altImageTags = array()) { preg_match_all(self::getImageRegex($altImageTags), $a, $matches); preg_match_all(self::getImageRegex($altImageTags), $b, $matches2); if (sizeof($matches) != sizeof($matches2)) { return false; } for ($n = 0; $n < sizeof($matches); $n++) { if (is_array($matches[$n])) { if (sizeof($matches[$n]) != sizeof($matches2[$n])) { return false; } for ($m = 0; $m < sizeof($matches[$n]); $m++) { $matches[$n][$m] = Wikitext::removeImageCaption($matches[$n][$m]); $matches2[$n][$m] = Wikitext::removeImageCaption($matches2[$n][$m]); if ($matches[$n][$m] != $matches2[$n][$m]) { return false; } } } else { $matches[$n][$m] = Wikitext::removeImageCaption($matches[$n][$m]); $matches2[$n][$m] = Wikitext::removeImageCaption($matches2[$n][$m]); if ($matches[$n] != $matches2[$n]) { return false; } } } return true; }
<?php require_once 'commandLine.inc'; $dbw = wfGetDB(DB_MASTER); print "Getting articles...\n"; $wgUser = User::newFromName('MiscBot'); $title_array = array('Make-a-LEGO-Key-Holder', 'Use-DigiArty-WinX-DVD-Author', 'Make-a-Shanghai-Cocktail', 'Switch-Tabs-in-Chrome', 'Catch-Walleye', 'Detect-Nofollow-Links', 'Make-a-Line-Plot', 'Make-the-Drink-the-Brain', 'Calculate-Stocking-Rates-for-Your-Pastures', 'Plead-Against-a-Ban-on-RuneScape', 'Make-Idli-Gunpowder-(Molagapodi)', 'Treat-Costochondritis', 'Enjoy-Calculus', 'Remove-Pips-from-Grapes', 'Alleviate-a-Sore-Nose-With-Petroleum-Jelly', 'Crochet-Shawls', 'Clean-and-Disinfect-Ice-Trays', 'Record-an-Upright-Acoustic-Bass', 'Make-a-Survival-Kit-in-a-Bottle', 'Carry-a-Football', 'Fix-a-Leaking-Roof', 'Write-a-Robots.Txt-File', 'Cope-With-Disruptive-People-During-a-Movie', 'Have-a-Private-Conversation-in-Public', 'Celebrate-National-Poetry-Month', 'Have-Fun-With-People-That-You-Don%27t-Like', 'Make-Premium-Pizzeria-Pizza', 'Create-a-Feeding-Routine-for-Your-Dog', 'Make-Hydrogen-from-Muriatic-Acid', 'Integrate-Music-Into-Creative-Writing', 'Be-an-Awesome-Girl-Without-Being-Athletic', 'Do-a-Buoyancy-Check', 'Make-Dryer-Sheets', 'Recite-the-Spanish-Alphabet', 'Use-Magnets-to-Locate-Studs', 'Do-Drive-By-Editing-While-Patrolling-wikiHow', 'Avoid-Awkward-Silences-when-You-Meet-Someone-Again-After-Sleeping-With-Them', 'Copy-an-Encrypted-DVD-to-a-Smaller-Capacity', 'Organize-Cloth-Diapers', 'Love-Your-Child-(Indian-Culture)', 'Cook-Fish-in-a-Double-Boiler', 'Get-Someone-to-Let-You-Draw-Them-Naked', 'Tie-a-Snapping-Turtle-So-It-Won%27t-Bite-You', 'Record-a-Kick-Drum', 'Reject-a-Homecoming-Date-(Girls)', 'Diagnose-High-Thyroid-Levels-in-a-Cat', 'Plan-a-Date-for-a-Foodie', 'Brew-Amber-Beer', 'Choose-an-Online-Dog-Training-Course', 'Make-Pickles-from-Leftover-Brine', 'Eradicate-the-Fear-of-Stuttering', 'Create-Nintendo-Wii-Skins', 'Convince-Your-Parents-to-Celebrate-4th-of-July', 'Improve-Your-Swim-School-Business', 'Unlock-the-Death-Count-in-Super-Mario-Galaxy', 'Buy-a-Waterproof-Camera', 'Make-Mock-Chicken-Filling', 'Make-Yogurt-Berry-Muffins', 'Make-a-Sphagnum-Moss-Wreath', 'Resist-the-Firemen%27s-Carry', 'Change-Instruments-from-Bb-Clarinet-to-Soprano-Saxophone', 'Get-the-Best-from-Fine-Scotch-Whiskies', 'Avoid-Unscrupulous-Bad-Credit-Loan-Brokers', 'Take-Care-of-a-Deaf-Great-Dane', 'Have-a-Gay-Marriage-in-New-York-Even-if-the-Church-Says-No', 'Protest-TSA-Screening-As-Sexual-Assault', 'Keep-Germs-off-Your-Purse', 'Teach-Your-Kids-to-Enjoy-Classic-Books', 'Appreciate-Patrick-Swayze', 'Cut-Down-on-Your-Medical-Costs', 'Change-the-Feel-of-a-Scene', 'Market-Your-Music-Like-Sir-Alan-Sugar', 'Make-Watercress-Potato-Salad', 'Be-a-Word-Collector', 'Get-the-IP-Address-of-Any-Website', 'Read-Supermarket-Labels', 'Make-Teriyaki-Grilled-Corn', 'Visit-the-Westminster-Clock-Tower', 'Build-a-Childrens-Ministry', 'Go-Green-at-the-Trade-Show', 'Pick-a-Mezuzah-Case', 'Get-a-Steady-Violin-Bow', 'Take-Your-Dog-for-a-Walk-in-Winter', 'Make-Wheat,-Beet-and-Walnut-Salad', 'Edit-wikiHow-Using-an-iPod-Touch', 'Make-Orange-(the-Fruit)-Jelly-Pumpkins', 'Leave-Home-for-the-First-Time', 'Hold-a-Cello-when-Resting', 'Destroy-a-Fortified-Position-in-Nerf', 'Get-a-Friend-to-Stop-Playing-the-Race-Card', 'Follow-Recent-Earthquakes-in-New-Zealand', 'Get-over-Your-Fear-of-Banks', 'Enjoy-the-Process-of-Drawing-Despite-Any-Messups', 'Get-to-Glasgow', 'Persuade-a-Friend-to-Let-You-Borrow-Her-Clothes', 'Look-Like-a-Tennis-Player', 'Make-Orange-and-Mustard-Chicken-Drummers', 'Wear-Boyfriend-Jeans', 'Vote-for-American-Idol', 'Use-the-Internet', 'Use-a-Proxy', 'Get-Good-at-Quick-Scoping-and-No-Scoping-on-Call-of-Duty-Black-Ops', 'Prune-Clematis', 'Play-Dota-2', 'Make-Hot-Fudge', 'Make-French-Onion-Soup', 'Make-a-Drum', 'Live', 'Have-Fun-With-Friends', 'Fly-in-Pandaria', 'Evolve-Clamperl-in-Pokemon', 'Come-out-of-One%27s-Shell', 'Catch-a-Pokemon-(Advanced)', 'Breed-the-Rainbow-Dragon-on-DragonVale', 'Update-Minecraft-for-the-Xbox-360-Version', 'Force-a-Burp', 'Immigrate-Into-the-United-States-Permanently', 'Install-Google-Talk-on-Your-Computer', 'Make-YouTube-Stop-Buffering', 'Burn-an-ISO-File-on-Windows-7', 'Do-the-%22Gallon-of-Milk%22-Challenge', 'Get-Unlimited-Money-on-the-Sims-3-for-PC', 'Camp-in-Call-of-Duty-Ghosts', 'Get-Hats-in-Team-Fortress-2', 'Start-a-Writer%27s-Notebook', 'Install-Windows-8-from-USB', 'Know-if-Your-Fish-Is-Male-or-Female', 'Use-a-Computer-Printer', 'Cook-Green-Split-Peas', 'Cook-Steak-in-the-Oven-So-It%27s-Tender', 'Adopt-a-Kid-in-the-Sims-3', 'Put-a-SIM-Card-Into-an-iPhone-3GS', 'Trim-a-String-in-Java', 'Make-Lavender-Tea', 'Change-Your-Name-in-Massachusetts', 'Make-a-Coffee-Milkshake', 'Make-Your-Own-Emergency-Eyeliner', 'Fix-Yu-Gi-Oh-Power-of-Chaos%27s-Data-Saving-Problem', 'Export-Audio-in-Audacity', 'Grow-Breasts-Without-Surgery', 'Use-Nasturtiums-in-Food', 'Catch-Bagon-on-Pokemon-Ruby', 'Use-Yahoo!-Answers', 'Transfer-Contacts-from-Windows-Mobile-Phone-to-Pc-with-GodswMobile.Com', 'Remove-an-Application-Off-Your-Twitter-Account', 'Edit-a-Facebook-Business-Page', 'Delete-Something-from-the-History-Section-of-Favourites', 'Make-a-Microphone-from-a-Speaker', 'Get-Rid-of-a-Beer-Belly', 'Live-a-Holistic-Life-of-Personal-Development', 'Get-Pichu-in-Pokemon-Ruby', 'Get-to-the-North-Pole', 'Delete-Your-iTunes-Library-(Mac)', 'Change-Your-Name-in-Kentucky', 'Get-a-Riolu-Egg-in-Pokemon-Diamond', 'Rent-a-Private-Mailbox', 'Incorporate-in-New-York', 'Text-a-Girl-(Young-Teens)', 'Fix-Usb-Device-Not-Recognized-Error', 'Find-the-Best-Muscle-Building-Workout', 'Access-a-Web-Page-That-Doesn%27t-Load-Fully', 'Be-Friends-With-Everyone-in-Sims-2', 'Hold-a-Guitar', 'Disable-a-Stolen-Mobile-Phone', 'Grow-Bird%27s-Nest-Fern-As-an-Indoor-Plant', 'Travel-with-Your-Guitar', 'Be-Familiar-with-the-Falcon-Crest-TV-Series', 'Use-E-Liquid', 'Draw-a-Sad-Face', 'Evolve-Electabuzz', 'Dump-Your-Boyfriend-in-Middle-School', 'Look-Goth-While-Traveling-for-a-Long-Time-on-a-Plane', 'Jailbreak-Your-iDevice-Right-from-It', 'Call-and-Text-With-Google-Voice-on-an-iPod-Touch', 'Build-a-Snail-House', 'Create-a-Website-With-Weebly.Com', 'K-Style-in-Gunz', 'Be-Bad', 'Be-Optimistic-in-a-Pessimistic-World', 'Become-a-Playback-Singer-in-Mumbai', 'Set-up-FTP-in-cPanel', 'Bypass-Impero-Blocking', 'Choose-Shaolin-Kung-Fu-Style', 'Use-an-Overhead-Projector', 'Make-Hair-Gel-Using-Aloe-Vera-Pulp', 'Have-Fresh-Breath', 'Make-a-Quick-Comic-Book', 'Make-a-Roblox-Username', 'Remove-DRM-from-Amazon-Video-on-Demand', 'Sound-Exactly-Like-Green-Day-for-Under-$500', 'Qualify-for-Innocent-Spouse-Tax-Relief', 'Dye-Your-Hair-with-a-Sharpie-Marker', 'Find-the-Big-Dipper', 'Create-the-Ultimate-Stamina-Type-Metal-Fight-Beyblade', 'Make-Windows-7-Calculator-Crash', 'Perform-a-Math-Trick', 'Use-Retinol', 'Get-Console-on-Counter-Strike-Source', 'Close-Your-Golf-Stance', 'Remove-a-Door-Panel-on-a-Chevy-Tracker', 'Apply-Individual-Eyelashes', 'Practise-Your-Weaker-Foot-for-Soccer', 'Obtain-a-Kentucky-Concealed-Deadly-Weapons-License', 'Get-a-Boyfriend-on-Animal-Jam', 'Practice-Drum-Rolls', 'Change-Your-Modern-Warfare-2-Name-Color', 'Play-Blindfolded-Makeover', 'Make-Easy-No-Bake-Cheesecake', 'Check-Your-Webpage-Loading-Time-with-Google-Analytics', 'Give-Your-Dog-a-Massage', 'Avoid-Awkward-Conversations', 'Check-Linux-Distribution', 'Host-a-Shower-for-a-Second-Wedding', 'Return-to-Sender', 'Deal-With-Parents', 'Fix-Slippery-Basketball-Shoes', 'Use-an-MLS', 'Check-Your-PSP-Firmware', 'Apply-for-a-Marriage-License-in-Nevada', 'Turn-Safely-on-a-Motorcycle', 'Look-Great-for-Swimming', 'Make-Nickelodeon-Slime', 'Set-up-a-Laptop-Computer-Station', 'Write-Declarative-Sentences', 'Open-the-Shed-on-Virtual-Families', 'Change-Pink-Paint-Into-an-Orange-Color', 'Sync-Files-Between-Computers-Using-Dropbox', 'Measure-a-Box', 'Do-a-Cartwheel-in-Gymnastics', 'Save-Text-Messages-on-a-Cell-Phone', 'Remove-Screws-That-Have-Been-Painted-Over', 'Commit-to-a-Relationship', 'Hit-the-Smash-Shot-in-Table-Tennis', 'Roleplay-a-Warrior-Cat-Online', 'Do-General-Maintenance-on-Airsoft-Gas-Blowback-Pistols', 'Write-a-Cheesy-Song', 'Make-a-Collage-Poster', 'Operate-a-CB-Radio', 'Do-a-Frontflip-With-a-Full-Twist-in-Gymnastics', 'Get-a-Soccer-Coaching-License', 'Act-Like-a-Hunter-from-Left-4-Dead', 'Draw-Insects', 'Win-a-Zynga-Poker-Sit-and-Go-Tournament', 'Handle-Being-Stuck-in-the-Middle-of-a-Fight', 'Become-an-Accountant-in-Florida', 'Do-a-Side-Effect', 'Get-Cat-Hairs-off-Your-Tongue', 'Tell-if-It-Is-Raining', 'Make-Your-Glasses-White-by-Reflection', 'Get-Ink-Flowing-in-Gel-Pens', 'Apply-for-a-Citibank-Credit-Card', 'Take-an-Online-Defensive-Driving-Course-for-Ticket-Dismissal-in-Florida', 'Set-a-GPS-with-a-Location', 'Deal-With-a-Guy-Who-Has-Used-You', 'Care-for-an-Ant', 'Tell-a-Girl-She-Has-Nice-Feet', 'Talk-Like-Stitch', 'Stop-a-Horse-from-Chewing-Wood', 'Make-Canadian-Style-Steak-Seasoning', 'Use-Nearbytweets.Com-to-Find-Tweeters-Near-You', 'Get-the-Rarest-Fish-on-Fish-Tycoon', 'Set-a-Noise-Gate-for-Vocals', 'Comment-in-HTML', 'Stop-Corruption-in-Your-Work-Place', 'Learn-Welsh', 'Decorate-a-Square-Living-Room', 'Defeat-Silver-the-Hedgehog-in-Sonic-the-Hedgehog-Next-Gen', 'Design-a-Simple-Web-Page-in-Div', 'Get-the-Best-Deal-when-Trading-Games-in-at-Gamestop', 'Ride-an-Electric-Scooter', 'Convince-Your-Parents-to-Get-You-a-Double-Bed', 'Perform-a-Shining-Wizard-Combo-Move-in-Pro-Wrestling', 'Thicken-Fake-Blood', 'Recover-Lost-Filezilla-FTP-Client-Passwords', 'Have-to-Pack-Your-Bag-for-Cheerleading', 'Make-a-Fart-Noise-With-a-Straw', 'Save-All-Your-Pocket-Money-Without-Spending-It', 'Act-Like-Spongebob-Squarepants', 'Build-a-Computer-Using-Tangible-Acoustic-Interfaces', 'Attract-Latin-Guys', 'Sleep-With-Your-Best-Friend-Nude', 'Cure-Hiccups-With-the-Sugar-Method', 'Prove-that-you-are-an-Eminem-Fan', 'Skip-and-Criss-Cross', 'Create-a-Template-for-Your-ID-Cards', 'Get-Tested-for-Chlamydia', 'Be-an-Easygoing-Parent', 'Be-Friends-With-Someone-Who-Shares-Your-First-Name', 'Do-a-Right-Leap', 'Create-a-Facebook-Account-Behind-Your-Parents-Back', 'Set-up-a-Spy-or-CSI-Agency', 'Activate-a-Blackberry-on-BES', 'Prevent-a-Dog-and-Cat-Tapeworm-Infection-(Dipylidium-Infection)', 'Not-Kick-in-Bed', 'Celebrate-Beltane', 'Cope-with-a-Staff-Shortage', 'Avoid-a-Guy-at-School', 'Draw-a-Lego-Spiderman', 'Build-Muscle-for-Weightlifting', 'Develop-a-Southern-Accent', 'Snowshoe', 'Make-a-Lean-To-Shelter', 'Make-Mini-Fruit-Pizzas-on-Sugar-Cookies', 'Recognize-a-Handball-in-Soccer', 'Find-Insurance-Records-from-a-Previous-Owner-of-a-Car', 'Use-Lowe%27s-Coupons', 'Come-up-With-a-Great-Quiz-Idea', 'Have-a-Beyonce-Makeup-Look', 'Pitch-Submarine', 'Make-a-Diaper-for-a-Male-Dog', 'Avoid-Keeping-Hair-Dye-in-Too-Long', 'Guess-Someone%27s-Age-Correctly', 'Convince-Your-Parents-to-Let-You-Buy-a-Mouse', 'Play-Fade-to-Black', 'Get-a-Homeschooled-Girl-to-Like-You', 'Buy-a-Video-Capture-Card', 'Be-an-Anti-Emo-Christian', 'Fix-a-Hanging-GM-Headliner', 'Break-up-With-Someone-Without-Hurting-Their-Feelings', 'Find-Someone-Else%27s-Marriage-License', 'Measure-Ski-Poles', 'Become-a-Real-Life-Tekken-Fighter', 'Improve-Your-Beer-Bong%27s-Effectiveness', 'Write-a-Romantic-Poem-at-the-Top-of-Your-Head', 'Thank-Someone-for-Coming-to-Your-Graduation-Party', 'Execute-a-Go-Around-in-a-Cessna-172', 'Order-a-Free-Watchtower-Bible', 'Decorate-a-Tween-Girl%27s-Room', 'Make-Your-Clothes-Emo-or-Goth', 'Act-Like-an-Addams-from-the-Addams-Family', 'Know-How-Often-to-Instant-Message-Someone-Without-Being-Clingy', 'Speak-With-a-Hindu-Accent', 'Watch-Football-on-Android', 'Make-a-Kissgloss-Lip-Scrub', 'Catch-Sardines-in-RuneScape', 'Invest-in-a-Store-in-Oblivion', 'Draw-a-Kiwi', 'Put-Together-a-Goodie-Bag', 'Deal-With-a-Crush-on-a-Relative', 'Play-with-Earthshaker-in-Defense-of-the-Ancients-(DotA)', 'Remove-Strawberry-Stains', 'Play-Smash-Well', 'Buy-a-50th-Wedding-Anniversary-Gift', 'Take-a-Bath-Without-Getting-Your-Hair-Wet', 'Complete-All-Poptropica-Islands-Quickly', 'Make-Aromatic-Blend-Bath-Salts', 'Find-Out-Your-GMAT-Results', 'Remove-Wax-from-Concrete', 'Highlight-the-Mouth-With-Makeup', 'Do-an-Impression', 'Be-a-Girly-Tomboy-in-Fifth-Grade', 'Do-the-Moonwalk-Forwards', 'Catch-a-Ditto-in-Pokemon-Diamond', 'Find-the-Best-Online-Dating-Sites', 'Recover-from-a-Bad-Round-of-Golf', 'Make-Money-by-Selling-Shirts-Online-for-Free', 'Find-Video-Game-Cheats-Online', 'Cut-Holes-in-a-T-Shirt', 'Buy-a-Personal-Jet', 'Place-the-Cake-at-Your-Wedding-Reception', 'Eat-Gross-Food', 'Communicate-With-Your-Spouse', 'Get-Plenty-of-Sleep-Before-a-Test', 'Get-Pid-in-Java', 'Kill-Most-Bosses-in-Resident-Evil-4', 'Hatch-Frog-Eggs', 'Make-a-Justin-Bieber-Poster', 'Be-a-Feminist-Without-Displaying-Your-Victimhood-Complex', 'Create-a-Clan-Cat', 'Not-Start-Drama', 'Buy-a-Shaver', 'Make-a-Barbie-Cooking-Show', 'Use-Spell-Scrolls-in-Ultima-IX-Multiple-Times-Without-Losing-the-Scroll', 'Buy-a-Keg', 'Make-the-Laptop-More-Secure-Operating-System', 'Choose-an-Iron-Supplement', 'Have-a-Fake-Phone-Conversation', 'Spot-a-Manipulator', 'Stop-a-Dog-from-Climbing-up-on-Things', 'Prevent-Your-Computer-from-Restarting-in-the-Middle-of-the-Night', 'Act-As-More-Than-One-Anime-Character-at-Once', 'Calculate-Family-Medical-and-Leave-Act-Leave-Time-Used', 'Evolve-Pichu-Into-Pikachu-on-Pokemon-Diamond', 'Be-the-Perfect-Bride', 'Fix-Avast-Setup-Registry-Errors', 'Make-Money-With-Domain-Parking', 'Kill-Your-Sim-With-Fire-on-the-Sims-2', 'Get-Leafeon-on-Pokemon-Diamond,-Pearl,-or-Platinum', 'Catch-Cod', 'Keep-Calm-on-Exam-Results-Day', 'Add-Moderators-to-a-Chat-Room-on-Justin.Tv', 'Shift-on-a-Quad-With-Clutch'); print "Done. Let us process the " . count($title_array) . " articles.\n"; $count = 0; foreach ($title_array as $title_name) { $title = Title::newFromText($title_name); if (!$title) { continue; } $rev = Revision::loadFromTitle($dbw, $title); if ($rev) { $wikitext = $rev->getText(); $intro = Wikitext::getIntro($rev->getText()); if (preg_match("@{{stub[^}]*}}@i", $intro)) { $intro = preg_replace("@{{stub[^}]*}}@i", "", $intro); $wikitext = Wikitext::replaceIntro($wikitext, $intro, true); print "Removing from: " . $title->getText() . "\n"; $article = new Article($title); $article->doEdit($wikitext, "Removing incorrectly placed stub template"); $count++; } } } print "Deleted from {$count} articles\n";
$dbr = wfGetDB(DB_SLAVE); $sql = "SELECT page_title, page_id FROM page WHERE page_is_redirect=0 AND page_namespace=" . NS_MAIN; $res = $dbr->query($sql, __FILE__); $fp = fopen('short-intros.csv', 'w'); if (!$fp) { die("could not open file for write\n"); } fputcsv($fp, array('page_id', 'URL', 'has_template', 'intro_length', 'intro')); foreach ($res as $row) { $title = Title::newFromDBkey($row->page_title); if (!$title) { print "Can't make title out of {$row->page_title}\n"; continue; } $rev = Revision::newFromTitle($title); $wikitext = $rev->getText(); $intro = Article::getSection($wikitext, 0); $flat = Wikitext::flatten($intro); $flat = trim($flat); $len = mb_strlen($flat); if ($len < 50) { // check whether it has either the {{intro or {{introduction template $hasTemplate = strpos(strtolower($intro), '{{intro') !== false; $fields = array($row->page_id, 'http://www.wikihow.com/' . $title->getPartialURL(), $hasTemplate ? 'y' : 'n', $len, $flat); fputcsv($fp, $fields); if (@++$i % 100 == 0) { print "article {$i}\n"; } } } fclose($fp);
public function mobileSearch($q, $start, $limit = 20) { global $wgOut, $wgMemc; // Don't return more than 50 search results at a time to prevent abuse if ($limit > 50) { $limit = 50; } $key = wfMemcKey("MobileSearch", str_replace(" ", "-", $q), $start, $limit); if ($val = $wgMemc->get($key)) { return $val; } $contents = $this->googleSearchResultTitles($q, $start, $limit, 0, self::SEARCH_MOBILE); $results = array(); foreach ($contents as $t) { // Only return articles if ($t->getNamespace() != NS_MAIN) { continue; } $result = array(); $result['title'] = $t->getText(); $result['url'] = $t->getFullURL(); $result['imgurl'] = wfGetPad(SkinWikihowskin::getGalleryImage($t, 103, 80)); $result['intro'] = null; if ($r = Revision::newFromid($t->getLatestRevID())) { $intro = Wikitext::getIntro($r->getText()); $intro = trim(Wikitext::flatten($intro)); $result['intro'] = substr($intro, 0, 180); // Put an ellipsis on the end $len = strlen($result['intro']); $result['intro'] .= substr($result['intro'], $len - 1, $len) == '.' ? ".." : "..."; } if (!is_null($result['intro'])) { $results[] = array('article' => $result); } } $searchResults['results'] = $results; $json = json_encode($searchResults); $wgMemc->set($key, $json, 3600); // 1 hour header("Content-type: application/json"); $wgOut->disable(true); echo $json; }
public static function getEdits($articleId) { $dbr = wfGetDB(DB_SLAVE); $gr = 0; $gr = $dbr->selectField('good_revision', array('gr_rev'), array('gr_page' => $articleId)); $edits = self::getSigEdits($gr); if ($edits) { return $edits; } $res = $dbr->select(array('revision', 'text'), array('rev_id', 'old_text', 'old_flags', 'rev_timestamp', 'rev_user', 'rev_user_text'), array('rev_page' => $articleId, 'rev_text_id = old_id'), __METHOD__, array('order by' => 'rev_timestamp asc')); $txts = array(); $grTxt = false; foreach ($res as $row) { $flags = explode(',', $row->old_flags); $rowText = Revision::decompressRevisionText($row->old_text, $flags); $stepsSection = Wikitext::getStepsSection($rowText); //print("Got txt for rev" . $row->rev_id . "\n"); $txts[] = array('text' => $stepsSection[0], 'rev_page' => $row->rev_page, 'rev_id' => $row->rev_id, 'rev_user' => $row->rev_user, 'rev_user_text' => $row->rev_user_text); if ($row->rev_id == $gr) { $grTxt = $stepsSection[0]; break; } } if (!$grText) { $grText = $txts[sizeof($txts) - 1]['text']; $gr = $txts[sizeof($txts) - 1]['rev_id']; } global $wgContLang; $segmentedGr = $wgContLang->segmentForDiff($grText); $grArr = explode("\n", $segmentedGr); $grSize = strlen($segmentedGr) - sizeof($grArr) + 1; // Amount added $added = 0; $edits = array(); $first = true; $lastAdds = 0; foreach ($txts as $txt) { $txtArr = explode("\n", $wgContLang->segmentForDiff($txt['text'])); //print("diff for rev " . $txt['rev_id'] . " " . wfTimestampNow() . "\n"); $diffs = new Diff($txtArr, $grArr); $adds = 0; foreach ($diffs as $diff) { foreach ($diff as $d) { if ($d->type == 'copy') { foreach ($d->closing as $cl) { $adds += strlen($cl); } } elseif ($d->type == 'change') { $wld = new WordLevelDiff($d->orig, $d->closing); foreach ($wld->edits as $edit) { if ($edit->type == 'copy') { foreach ($edit->orig as $o) { $adds += strlen($o); } } } } } } if ($adds > $added) { $newAdded = $adds - $added; $added = $adds; } else { $newAdded = 0; } if ($newAdded > 0) { // First edit or didn't add steps // This prevents counting the steps section formatting fix as a contributor if ($first || $lastAdds != 0) { $edits[] = array('added' => $newAdded, 'gr' => $gr, 'rev' => $txt['rev_id'], 'page' => $txt['page_id'], 'user' => $txt['rev_user'], 'username' => $txt['rev_user_text']); } } $first = false; $lastAdds = $adds; } if ($edits) { self::saveSigEdits($edits); } return $edits; }
function getDocData($row, $noImages) { $page_id = $row->page_id; $page_counter = $row->page_counter; $title = Title::newFromDBkey($row->page_title); if (!$title || !$title->exists()) { decho("unknown title for id", $page_id, false); return ""; } $title_text = "<![CDATA[" . wfMsg('howto', $title->getText()) . "]]>"; if (!$noImages) { $image = Wikitext::getTitleImage($title, true) ?: AppDataFormatter::getCategoryImageFile($title); } if ($image) { $heightPreference = $image->getWidth() > $image->getHeight(); $thumb = WatermarkSupport::getUnwatermarkedThumbnail($image, AppDataFormatter::SEARCH_THUMB_WIDTH, AppDataFormatter::SEARCH_THUMB_HEIGHT, true, true, $heightPreference); } if ($thumb && !$thumb instanceof MediaTransformError) { $thumbUrl = AppDataFormatter::uriencode(wfGetPad($thumb->url)); } $update = ""; if ($noImages) { $update = 'update="set"'; } $postData = '<doc>' . '<field name="id">' . $page_id . '</field>' . '<field name="title" ' . $update . '>' . $title_text . '</field>' . '<field name="page_counter" ' . $update . '>' . $page_counter . '</field>'; if ($thumbUrl) { $postData .= '<field name="image_58x58">' . $thumbUrl . '</field>'; } $postData .= '</doc>'; return $postData; }
static function choose($articles) { $consumed = array(); $consumeArticle = function (&$spot, $i) use(&$articles, &$consumed) { $spot = array('title' => @$articles[$i]['title'], 'image' => @$articles[$i]['image'], 'dims' => $spot); $consumed[] = $i; }; $taller = self::findFirstTall($articles); $large = self::findFirstLarge($articles, $consumed); // Get formats based on whether there is an image that could // work as a 1x2 image // Disable Tall formats for now since they are causing problems $possibleFormats = self::getPossibleWideFormats(); $seed = self::stringToNumber($articles[0]['image']->getSha1()); mt_srand($seed); $pos = mt_rand(0, count($possibleFormats) - 1); $format = $possibleFormats[$pos]; // Only consider the first count($articles) - $trim articles // from the stream because we don't want to leave out of order // elements unconsumed. $spots = 0; foreach ($format as $spot) { if ($spot) { $spots++; } } if (count($articles) > $spots) { array_splice($articles, $spots); } // If we have a suitable 1x2 image, use it first -- there is at // most one 1x2 image per format if ($taller >= 0) { foreach ($format as &$spot) { // find the taller image spot if ($spot == '1x2') { $consumeArticle($spot, $taller); break; } } } // If we have a suitable 2x2 image, use that next -- this is at // most one 2x2 image per format if ($large >= 0) { foreach ($format as &$spot) { if (is_string($spot) && $spot == '2x2') { $consumeArticle($spot, $large); break; } } } // Next, sort the images by "flatness" to put the appropriate // images into 2x1 slots. There can be multiple 2x1 slots in a // format. $flatness = self::sortByFlatness($articles, $consumed); foreach ($format as &$spot) { if (count($flatness) == 0) { break; } if (is_string($spot) && $spot == '2x1') { $flat = array_shift($flatness); // Make the default image the wide one if (preg_match("@Default_wikihow_(green|blue)(_intl)?.png@", $articles[$flat]['image']->getPath())) { $articles[$flat]['image'] = Wikitext::getDefaultTitleImage($articles[$flat]['title'], true); } $consumeArticle($spot, $flat); } } // Fill the rest of the spots with the rest of the articles -- // this should only be 1x1 elements now. $i = 0; foreach ($format as &$spot) { // skip already consumed articles while (in_array($i, $consumed)) { $i++; } if (!$spot || !is_string($spot)) { // nothing } elseif ($i < count($articles)) { $consumeArticle($spot, $i); $i++; } else { $spot = array('title' => null, 'image' => null, 'dims' => $spot); } } return array($format, $consumed); }
static function getArticleImage($title, $sections = array()) { // calling get title image with skip parser = true is faster even though comments indicate otherwise $image = Wikitext::getTitleImage($title, true); if ($image) { $image = self::getImageDetails($image); } if (!$image || !$image['url']) { // try any image on the page $image = self::findAnyImage($sections); } if (!$image || !$image['url']) { // still no image? get category image $image = self::getCategoryImageFile($title); if ($image) { $image = self::getImageDetails($image); } } return $image ?: array('obj' => '', 'url' => '', 'large' => ''); }
/** * Handle API calls to get the steps from an article */ private function doAPI() { global $wgRequest, $wgOut, $wgContLang; $articleIds = $wgRequest->getVal("articleIds"); $articleIds = preg_split("@,@", $articleIds); $dbr = wfGetDB(DB_SLAVE); $wgOut->setArticleBodyOnly(true); $articles = array(); foreach ($articleIds as $articleId) { if (is_numeric($articleId)) { $r = Revision::loadFromPageId($dbr, $articleId); if ($r) { $txt = $r->getText(); $intro = Wikitext::getIntro($txt); $text = Wikitext::getStepsSection($txt, true); if (is_array($text) && sizeof($text) > 0) { $articles[$articleId] = array("steps" => $text[0], "intro" => $intro, "altImageTags" => array($wgContLang->getNSText(NS_IMAGE))); } } } } $wgOut->addHTML(json_encode($articles)); }
/** * Parse and transform the document from the old HTML for NS_MAIN articles to the new mobile * style. This should probably be pulled out and added to a subclass that can then be extended for * builders that focus on building NS_MAIN articles */ protected function parseNonMobileArticle(&$article) { global $IP, $wgContLang, $wgLanguageCode; $sectionMap = array(wfMsg('Intro') => 'intro', wfMsg('Ingredients') => 'ingredients', wfMsg('Steps') => 'steps', wfMsg('Video') => 'video', wfMsg('Tips') => 'tips', wfMsg('Warnings') => 'warnings', wfMsg('relatedwikihows') => 'relatedwikihows', wfMsg('sourcescitations') => 'sources', wfMsg('thingsyoullneed') => 'thingsyoullneed', wfMsg('article_info') => 'article_info'); $lang = MobileWikihow::getSiteLanguage(); $imageNsText = $wgContLang->getNsText(NS_IMAGE); $device = $this->getDevice(); // munge steps first $opts = array('no-ads' => true); $article = WikihowArticleHTML::postProcess($article, $opts); // Make doc correctly formed $articleText = <<<DONE <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{$lang}" lang="{$lang}"> <head> \t<meta http-equiv="Content-Type" content="text/html; charset='utf-8'" /> </head> <body> {$article} </body> </html> DONE; require_once "{$IP}/extensions/wikihow/mobile/JSLikeHTMLElement.php"; $doc = new DOMDocument('1.0', 'utf-8'); $doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement'); $doc->strictErrorChecking = false; $doc->recover = true; //$doc->preserveWhiteSpace = false; //$wgOut->setarticlebodyonly(true); @$doc->loadHTML($articleText); $doc->normalizeDocument(); //echo $doc->saveHtml();exit; $xpath = new DOMXPath($doc); // Delete #featurestar node $node = $doc->getElementById('featurestar'); if (!empty($node)) { $node->parentNode->removeChild($node); } $node = $doc->getElementById('newaltmethod'); if (!empty($node)) { $node->parentNode->removeChild($node); } // Remove all "Edit" links $nodes = $xpath->query('//a[@id = "gatEditSection"]'); foreach ($nodes as $node) { $node->parentNode->removeChild($node); } // Resize youtube video $nodes = $xpath->query('//embed'); foreach ($nodes as $node) { $url = ''; $src = $node->attributes->getNamedItem('src')->nodeValue; if (!$device['show-youtube'] || stripos($src, 'youtube.com') === false) { $parent = $node->parentNode; $grandParent = $parent->parentNode; if ($grandParent && $parent) { $grandParent->removeChild($parent); } } else { foreach (array(&$node, &$node->parentNode) as $node) { $widthAttr = $node->attributes->getNamedItem('width'); $oldWidth = (int) $widthAttr->nodeValue; $newWidth = $device['max-video-width']; if ($newWidth < $oldWidth) { $widthAttr->nodeValue = (string) $newWidth; $heightAttr = $node->attributes->getNamedItem('height'); $oldHeight = (int) $heightAttr->nodeValue; $newHeight = (int) round($newWidth * $oldHeight / $oldWidth); $heightAttr->nodeValue = (string) $newHeight; } } } } // Remove templates from intro so that they don't muck up // the text and images we extract $nodes = $xpath->query('//div[@class = "template_top"]'); foreach ($nodes as $node) { $node->parentNode->removeChild($node); } // Grab intro text $intro = ''; $nodes = $xpath->query('//body/div/p'); foreach ($nodes as $i => $node) { $text = $node->textContent; if (!empty($text) && $i == 0) { $introNode = $node; $intro = Wikitext::removeRefsFromFlattened($text); break; } } if ($introNode) { // Grab first image from article $imgs = $xpath->query('.//img', $introNode->parentNode); $firstImage = ''; foreach ($imgs as $img) { // parent is an <a> tag $parent = $img->parentNode; if ($parent->nodeName == 'a') { $href = $parent->attributes->getNamedItem('href')->nodeValue; if (preg_match('@(Image|' . $imageNsText . '):@', $href)) { $firstImage = preg_replace('@^.*(Image|' . $imageNsText . '):([^:]*)([#].*)?$@', '$2', $href); $firstImage = urldecode($firstImage); break; } } } // Remove intro node $parent = $introNode->parentNode; $parent->removeChild($introNode); } // Get rid of the <span> element to standardize the html for the // next dom query $nodes = $xpath->query('//div/span/a[@class = "image"]'); foreach ($nodes as $a) { $parent = $a->parentNode; $grandParent = $parent->parentNode; $grandParent->replaceChild($a, $parent); } // Resize all resize-able images $nodes = $xpath->query('//div/a[@class = "image"]/img'); $imgNum = 1; foreach ($nodes as $img) { $srcNode = $img->attributes->getNamedItem('src'); $widthNode = $img->attributes->getNamedItem('width'); $width = (int) $widthNode->nodeValue; $heightNode = $img->attributes->getNamedItem('height'); $height = (int) $heightNode->nodeValue; $imageClasses = $img->parentNode->parentNode->attributes->getNamedItem('class')->nodeValue; /* if (!stristr($imageClasses, "tcenter")) { $img->parentNode->parentNode->parentNode->attributes->getNamedItem('class')->nodeValue = ''; $img->parentNode->parentNode->parentNode->attributes->getNamedItem('style')->nodeValue = ''; } */ if (stristr($imageClasses, "tcenter") !== false) { $newWidth = $device['full-image-width']; $newHeight = (int) round($device['full-image-width'] * $height / $width); } else { $newWidth = $device['max-image-width']; $newHeight = (int) round($device['max-image-width'] * $height / $width); } $a = $img->parentNode; $href = $a->attributes->getNamedItem('href')->nodeValue; if (!$href) { $onclick = $a->attributes->getNamedItem('onclick')->nodeValue; $onclick = preg_replace('@.*",[ ]*"@', '', $onclick); $onclick = preg_replace('@".*@', '', $onclick); $imgName = preg_replace('@.*(Image|' . $imageNsText . '|' . urlencode($imageNsText) . '):@', '', $onclick); } else { $imgName = preg_replace('@^/(Image|' . $imageNsText . '|' . urlencode($imageNsText) . '):@', '', $href); } $title = Title::newFromURL($imgName, NS_IMAGE); if (!$title) { $imgName = urldecode($imgName); $title = Title::newFromURL($imgName, NS_IMAGE); } if ($title) { $image = RepoGroup::singleton()->findFile($title); if ($image) { list($thumb, $newWidth, $newHeight) = self::makeThumbDPI($image, $newWidth, $newHeight, $device['enlarge-thumb-high-dpi']); $url = wfGetPad($thumb->getUrl()); $srcNode->nodeValue = $url; $widthNode->nodeValue = $newWidth; $heightNode->nodeValue = $newHeight; // change surrounding div width and height $div = $a->parentNode; $styleNode = $div->attributes->getNamedItem('style'); //removing the set width/height $styleNode->nodeValue = ''; //$div->attributes->getNamedItem('class')->nodeValue = ''; /* if (preg_match('@^(.*width:)[0-9]+(px;\s*height:)[0-9]+(.*)$@', $styleNode->nodeValue, $m)) { $styleNode->nodeValue = $m[1] . $newWidth . $m[2] . $newHeight . $m[3]; } */ //default width/height for the srcset $bigWidth = 600; $bigHeight = 800; // change grandparent div width too $grandparent = $div; if ($grandparent && $grandparent->nodeName == 'div') { $class = $grandparent->attributes->getNamedItem('class'); if ($class) { $isThumb = stristr($class->nodeValue, 'mthumb') !== false; $isRight = stristr($class->nodeValue, 'tright') !== false; $isLeft = stristr($class->nodeValue, 'tleft') !== false; $isCenter = stristr($class->nodeValue, 'tcenter') !== false; if ($isThumb) { if ($isRight) { $style = $grandparent->attributes->getNamedItem('style'); $style->nodeValue = 'width:' . $newWidth . 'px;height:' . $newHeight . 'px;'; $bigWidth = 300; $bigHeight = 500; } elseif ($isCenter) { $style = $grandparent->attributes->getNamedItem('style'); $style->nodeValue = 'width:' . $newWidth . 'px;height:' . $newHeight . 'px;'; $bigWidth = 600; $bigHeight = 800; } elseif ($isLeft) { //if its centered or on the left, give it double the width if too big $style = $grandparent->attributes->getNamedItem('style'); $oldStyle = $style->nodeValue; $matches = array(); preg_match('@(width:\\s*)[0-9]+@', $oldStyle, $matches); if ($matches[0]) { $curSize = intval(substr($matches[0], 6)); //width: = 6 if ($newWidth * 2 < $curSize) { $existingCSS = preg_replace('@(width:\\s*)[0-9]+@', 'width:' . $newWidth * 2, $oldStyle); $style->nodeValue = $existingCSS; } } $bigWidth = 300; $bigHeight = 500; } } } } list($thumb, $newWidth, $newHeight) = self::makeThumbDPI($image, $bigWidth, $bigHeight, $device['enlarge-thumb-high-dpi']); $url = wfGetPad($thumb->getUrl()); $img->setAttribute('srcset', $url . ' ' . $newWidth . 'w'); //if we couldn't make it big enough, let's add a class if ($newWidth < $bigWidth) { $imgclass = $img->getAttribute('class'); $img->setAttribute('class', $imgclass . ' not_huge'); } //add the hidden info /* $newDiv = new DOMElement( 'div', htmlentities('test') ); $a->appendChild($newDiv); $newDiv->setAttribute('style', 'display:none;'); */ $a->setAttribute('id', 'image-zoom-' . $imgNum); $a->setAttribute('class', 'image-zoom'); $a->setAttribute('href', '#'); global $wgServerName; $href = $wgServerName . $href; if (!preg_match("/^http:\\/\\//", $href)) { $href = "http://" . $serverName . $href; } $href = preg_replace("/\\m\\./", "", $href); $href = preg_replace("/^http:\\/\\/wikihow\\.com/", "http://www.wikihow.com", $href); $details = array('url' => $url, 'width' => $newWidth, 'height' => $newHeight, 'credits_page' => $href); $newDiv = new DOMElement('div', htmlentities(json_encode($details))); $a->appendChild($newDiv); $newDiv->setAttribute('style', 'display:none;'); $newDiv->setAttribute('id', 'image-details-' . $imgNum); $imgNum++; } else { //huh? can't find it? well, then let's not display it $img->parentNode->parentNode->parentNode->parentNode->setAttribute('style', 'display:none;'); } } else { //huh? can't find it? well, then let's not display it $img->parentNode->parentNode->parentNode->parentNode->setAttribute('style', 'display:none;'); } } // Remove template from images, add new zoom one $nodes = $xpath->query('//img'); foreach ($nodes as $node) { $src = $node->attributes ? $node->attributes->getNamedItem('src') : null; $src = $src ? $src->nodeValue : ''; if (stripos($src, 'magnify-clip.png') !== false) { $parent = $node->parentNode; $parent->parentNode->removeChild($parent); } } //get rid of the corners and watermarks $nodes = $xpath->query('//div[@class = "corner top_left" or @class = "corner bottom_left" or @class = "corner top_right" or @class = "corner bottom_right" or @class = "wikihow_watermark"]'); foreach ($nodes as $node) { $parent = $node->parentNode; $parent->removeChild($node); } //gotta swap in larger images if the client's width is big enough //(i.e. tablet et al) $nodes = $xpath->query('//img[@class = "mwimage101" or @class = "mwimage101 not_huge"]'); foreach ($nodes as $node) { //make a quick unique id for this $id = md5($node->attributes->getNamedItem('src')->nodeValue) . rand(); $node->setAttribute('id', $id); //pass it to our custom function for swapping in larger images $swap_it = 'if (isBig) WH.mobile.swapEm("' . $id . '");'; $scripttag = new DOMElement('script', htmlentities($swap_it)); $node->appendChild($scripttag); } // Change the width attribute from any tables with a width set. // This often happen around video elements. $nodes = $xpath->query('//table/@width'); foreach ($nodes as $node) { $width = preg_replace('@px\\s*$@', '', $node->nodeValue); if ($width > $device['screen-width'] - 20) { $node->nodeValue = $device['screen-width'] - 20; } } // Surround step content in its own div. We do this to support other features like checkmarks $nodes = $xpath->query('//div[@id="steps"]/ol/li'); foreach ($nodes as $node) { $node->innerHTML = '<div class="step_content">' . $node->innerHTML . '</div>'; } //remove quiz $nodes = $xpath->query('//div[@class = "quiz_cta"]'); foreach ($nodes as $node) { $node->parentNode->removeChild($node); } //remove quiz header $nodes = $xpath->query('//h3/span[text()="Quiz"]'); foreach ($nodes as $node) { $parentNode = $node->parentNode; $parentNode->parentNode->removeChild($parentNode); } //pull out the first 6 related wikihows and format them $nodes = $xpath->query('//div[@id="relatedwikihows"]/ul/li'); $count = 0; $related_boxes = array(); foreach ($nodes as $node) { if ($count > 6) { break; } //grab the title preg_match('@href=\\"\\/(.*?)?\\"@', $node->innerHTML, $m); $title = Title::newFromText($m[1]); if (!$title) { continue; } $temp_box = $this->makeRelatedBox($title); if ($temp_box) { $related_boxes[] = $temp_box; $last_node = $node; $parent = $node->parentNode; $last_parent = $parent; $parent->removeChild($node); $count++; } } //only 1? not enough. throw it back if ($count == 1) { $related_boxes = array(); $last_parent->appendChild($last_node); } // Inject html into the DOM tree for specific features (ie thumb ratings, ads, etc) $this->mobileParserBeforeHtmlSave($xpath); //self::walkTree($doc->documentElement, 1); $html = $doc->saveXML(); $sections = array(); $sectionsHtml = explode('<h2>', $html); unset($sectionsHtml[0]); // remove leftovers from intro section foreach ($sectionsHtml as $i => &$section) { $section = '<h2>' . $section; if (preg_match('@^<h2[^>]*>\\s*<span[^>]*>\\s*([^<]+)@i', $section, $m)) { $heading = trim($m[1]); $section = preg_replace('@^<h2[^>]*>\\s*<span[^>]*>\\s*([^<]+)</span>(\\s|\\n)*</h2>@i', '', $section); if (isset($sectionMap[$heading])) { $key = $sectionMap[$heading]; $sections[$key] = array('name' => $heading, 'html' => $section); } } } // Remove Video section if there is no longer a youtube video if (isset($sections['video'])) { if (!preg_match('@<object@i', $sections['video']['html'])) { unset($sections['video']); } } // Add the related boxes if (isset($sections['relatedwikihows']) && !empty($related_boxes)) { $sections['relatedwikihows']['boxes'] = $related_boxes; } // Add article info $sections['article_info']['name'] = wfMsg('article_info'); $sections['article_info']['html'] = $this->getArticleInfo($title); // Remove </body></html> from html if (count($sections) > 0) { $keys = array_keys($sections); $last =& $sections[$keys[count($sections) - 2]]['html']; $last = preg_replace('@</body>(\\s|\\n)*</html>(\\s|\\n)*$@', '', $last); } // Add a simple form for uploading images of completed items to the article if ($wgLanguageCode == 'en' && isset($sections['steps']) && isset($device['show-upload-images']) && $device['show-upload-images']) { require_once "{$IP}/extensions/wikihow/mobile/MobileUciHtmlBuilder.class.php"; $userCompletedImages = new MobileUciHtmlBuilder(); $sections['steps']['html'] .= $userCompletedImages->createByHtml($this->t); } return array($sections, $intro, $firstImage); }
static function getGalleryImage($title, $width, $height, $skip_parser = false) { global $wgMemc, $wgLanguageCode, $wgContLang; $cachekey = wfMemcKey('gallery1', $title->getArticleID(), $width, $height); $val = $wgMemc->get($cachekey); if ($val) { return $val; } if ($title->getNamespace() == NS_MAIN || $title->getNamespace() == NS_CATEGORY) { if ($title->getNamespace() == NS_MAIN) { $file = Wikitext::getTitleImage($title, $skip_parser); if ($file && isset($file)) { //need to figure out what size it will actually be able to create //and put in that info. ImageMagick gives prefence to width, so //we need to see if it's a landscape image and adjust the sizes //accordingly $sourceWidth = $file->getWidth(); $sourceHeight = $file->getHeight(); $heightPreference = false; if ($width / $height < $sourceWidth / $sourceHeight) { //desired image is portrait $heightPreference = true; } $thumb = $file->getThumbnail($width, $height, true, true, $heightPreference); if ($thumb instanceof MediaTransformError) { // we got problems! $thumbDump = print_r($thumb, true); wfDebug("problem getting thumb for article '{$title->getText()}' of size {$width}x{$height}, image file: {$file->getTitle()->getText()}, path: {$file->getPath()}, thumb: {$thumbDump}\n"); } else { $wgMemc->set($cachekey, wfGetPad($thumb->getUrl()), 2 * 3600); // 2 hours return wfGetPad($thumb->getUrl()); } } } $catmap = Categoryhelper::getIconMap(); // if page is a top category itself otherwise get top if (isset($catmap[urldecode($title->getPartialURL())])) { $cat = urldecode($title->getPartialURL()); } else { $cat = Categoryhelper::getTopCategory($title); //INTL: Get the partial URL for the top category if it exists // For some reason only the english site returns the partial // URL for getTopCategory if (isset($cat) && $wgLanguageCode != 'en') { $title = Title::newFromText($cat); if ($title) { $cat = $title->getPartialURL(); } } } if (isset($catmap[$cat])) { $image = Title::newFromText($catmap[$cat]); $file = wfFindFile($image, false); if ($file) { $sourceWidth = $file->getWidth(); $sourceHeight = $file->getHeight(); $heightPreference = false; if ($width / $height < $sourceWidth / $sourceHeight) { //desired image is portrait $heightPreference = true; } $thumb = $file->getThumbnail($width, $height, true, true, $heightPreference); if ($thumb) { $wgMemc->set($cachekey, wfGetPad($thumb->getUrl()), 2 * 3600); // 2 hours return wfGetPad($thumb->getUrl()); } } } else { $image = Title::makeTitle(NS_IMAGE, "Book_266.png"); $file = wfFindFile($image, false); if (!$file) { $file = wfFindFile("Book_266.png"); } $sourceWidth = $file->getWidth(); $sourceHeight = $file->getHeight(); $heightPreference = false; if ($width / $height < $sourceWidth / $sourceHeight) { //desired image is portrait $heightPreference = true; } $thumb = $file->getThumbnail($width, $height, true, true, $heightPreference); if ($thumb) { $wgMemc->set($cachekey, wfGetPad($thumb->getUrl()), 2 * 3600); // 2 hours return wfGetPad($thumb->getUrl()); } } } }
public function processHybridMedia($articleID, $creator, $videoList, $photoList) { $err = ''; $numSteps = 0; $replaced = 0; $vidBrTag = self::BRTAG_TO_VID ? self::BRTAG : ''; $imgBrTag = self::BRTAG_TO_IMG ? self::BRTAG : ''; self::d("processHybridMedia parse out steps section replacing it with a token, leaving the above and below wikitext intact"); // parse out steps section replacing it with a token, leaving // the above and below wikitext intact list($text, $url, $title) = $this->getArticleDetails($articleID); if (!$text || !$title) { $err = 'Could not find article ID ' . $articleID; } self::d("getArticleDetails: err:" . $err); if (!$err) { list($text, $steps, $stepsToken) = $this->cutStepsSection($text); if (!$stepsToken) { if (preg_match('@^(\\s|\\n)*#redirect@i', $text)) { $err = 'Could not parse Steps section out of article -- article text is #REDIRECT'; } else { $err = 'Could not parse Steps section out of article'; } } } $hybridMediaList = null; // try to place videos into wikitext, using tokens as placeholders. if (!$err) { $userIsScreenshotter = $this->isCreatorKnownScreenShotter($creator); list($err, $hybridMediaList) = $this->placeHybridMediaInSteps($articleID, $title, $videoList, $photoList, $text, $steps, $numSteps, $replaced, $userIsScreenshotter); } // detect if no photos and videos were to be processed if (!$err) { if (count($videoList) == 0 && count($photoList) == 0) { $err = 'No photos and videos to process'; } } // replace the tokens within the video or image tag if (!$err && $hybridMediaList && count($hybridMediaList) > 0) { $isAllLandscape = true; $hadColourProblems = false; $hadSizeProblems = false; $userIsScreenshotter = false; $isAllPhotoLandscape = count(photoList) > 0 ? true : false; $text = str_replace($stepsToken, $steps, $text); foreach ($hybridMediaList as &$media) { $video = $media['video']; if ($video) { //video related validation if (!empty($video['width']) && !empty($video['height']) && $video['width'] > $video['height']) { $sizeParam = WikiVisualTranscoder::VIDEO_LANDSCAPE_WIDTH; } else { $sizeParam = WikiVisualTranscoder::VIDEO_PORTRAIT_WIDTH; // Log first portrait video if (!$isAllLandscape) { $warning .= "portrait:{$video['name']}\n"; } $isAllLandscape = false; } // Log pixel width issues if (!$userIsScreenshotter && !$hadSizeProblems && !empty($video['width']) && $video['width'] < WikiVisualTranscoder::VIDEO_WARNING_MIN_WIDTH) { $warning .= "size:{$video['width']}px:{$video['name']}\n"; $hadSizeProblems = true; } } $image = $media['photo']; if ($image) { if (!empty($image['width']) && !empty($image['height']) && $image['width'] > $image['height']) { $sizeParam = WikiVisualTranscoder::IMAGE_LANDSCAPE_WIDTH; } else { $sizeParam = WikiVisualTranscoder::IMAGE_PORTRAIT_WIDTH; // Log first portrait image if (!$isAllPhotoLandscape) { $warning .= "portrait:{$image['name']}\n"; } $isAllPhotoLandscape = false; } // Detect colour profile issues if (!$hadColourProblems && !empty($image['filename'])) { $exifProfile = WikiPhoto::getExifColourProfile($image['filename']); if ($exifProfile && WikiPhoto::isBadWebColourProfile($exifProfile)) { $warning .= "colour:{$exifProfile}:{$image['name']}\n"; $hadColourProblems = true; } } // Log pixel width issues if (!$userIsScreenshotter && !$hadSizeProblems && !empty($image['width']) && $image['width'] < WikiVisualTranscoder::WARNING_MIN_WIDTH) { $warning .= "size:{$image['width']}px:{$image['name']}\n"; $hadSizeProblems = true; } // Log pixel width issues if (!$userIsScreenshotter && !$hadSizeProblems && !empty($image['width'])) { if ($image['width'] < WikiVisualTranscoder::WARNING_MIN_WIDTH) { $warning .= "size:{$image['width']}px:{$image['name']}\n"; $hadSizeProblems = true; } else { $maxImgDimen = $image['width'] > $image['height'] ? $image['width'] : $image['height']; if ($maxImgDimen > WikiVisualTranscoder::ERROR_MAX_IMG_DIMEN) { $err .= "size:{$image['width']}px > max size " . WikiVisualTranscoder::ERROR_MAX_IMG_DIMEN . "px:{$image['name']}\n"; $hadSizeProblems = true; } } } } self::d("video={$video}, image={$image}"); $mediaTag = null; if ($video && !$image) { //video only $mediaTag = $vidBrTag . '{{whvid|' . $video['mediawikiName'] . '|' . $video['previewMediawikiName'] . '}}'; $text = str_replace($video['token'], $mediaTag, $text); } elseif (!$video && $image) { //image only $mediaTag = $imgBrTag . '[[Image:' . $image['mediawikiName'] . '|center|' . $sizeParam . ']]'; $text = str_replace($image['token'], $mediaTag, $text); } elseif ($video && $image) { //hybrid $mediaTag = $vidBrTag . '{{whvid|' . $video['mediawikiName'] . '|' . $video['previewMediawikiName'] . '|' . $image['mediawikiName'] . '}}'; $text = str_replace($video['token'], $mediaTag, $text); } } } // remove certain templates from start of wikitext if (!$err) { $templates = array('illustrations', 'pictures', 'screenshots', 'stub'); $text = $this->removeTemplates($text, $templates); } // write wikitext and add/update wikivideo row if (!$err) { $err = $this->saveArticleText($articleID, $text); } // try to enlarge the uploaded photos of certain users if (!$err) { // now we want to ALWAYS enlarge the images for articles with ALL Landscape if ($isAllPhotoLandscape) { Wikitext::enlargeImages($title, true, AdminEnlargeImages::DEFAULT_CENTER_PIXELS); } } // if ($err) { // self::dbSetArticleProcessed($articleID, $creator, $err, $warning, $url, 0, $numSteps, 0, self::STATUS_ERROR); // } else { // self::dbSetArticleProcessed($articleID, $creator, '', $warning, $url, count($videoList), $numSteps, $replaced, self::STATUS_COMPLETE); // } // remove transcoding job db entries and s3 URIs //self::removeOldTranscodingJobs($articleID); $numPhotos = $photoList ? count($photoList) : 0; $numVideos = $photoList ? count($videoList) : 0; self::i("processed wikitext: {$creator} {$articleID} {$url} " . "photos=" . $numPhotos . ", " . "videos=" . $numVideos . " {$err}"); return array($err, $warning, $url, $numSteps, $replaced); // if ($err) { // self::dbSetArticleProcessed($articleID, $creator, $err, $warning, $url, 0, $numSteps, 0, self::STATUS_ERROR); // } else { // self::dbSetArticleProcessed($articleID, $creator, '', $warning, $url, count($videoList), $numSteps, $replaced, self::STATUS_COMPLETE); // } }
/** * Handle API calls to get the steps from an article */ private function doAPI() { global $wgRequest, $wgOut, $wgContLang; $articleIds = $wgRequest->getVal("articleIds"); $articleIds = preg_split("@,@", $articleIds); $dbr = wfGetDB(DB_SLAVE); $wgOut->setArticleBodyOnly(true); $articles = array(); foreach ($articleIds as $articleId) { if (is_numeric($articleId)) { $r = Revision::loadFromPageId($dbr, $articleId); if ($r) { $txt = $r->getText(); $intro = Wikitext::getIntro($txt); $text = Wikitext::getStepsSection($txt, true); $lines = preg_split("@\n@", $text[0]); $text = ""; // We remove extra lines technically in the 'steps' section, but which don't actually contain steps // Find the last line starting with a '#' $lastLine = 0; $n = 0; foreach ($lines as $line) { if ($line[0] == '#') { $lastLine = $n; } $n++; } // Truncate lines after the last line with a '#' $n = 0; foreach ($lines as $line) { if ($n > $lastLine) { break; } if ($n != 0) { $text .= "\n"; } $text .= $line; $n++; } if (strlen($text) > 0) { $articles[$articleId] = array("steps" => $text, "intro" => $intro, "altImageTags" => array($wgContLang->getNSText(NS_IMAGE))); } } } } $wgOut->addHTML(json_encode($articles)); }
$res = $dbr->select('page', 'page_id', array('page_namespace' => 0, 'page_is_redirect' => 0), __FILE__); while ($row = $dbr->fetchObject($res)) { $titles[$row->page_id] = array(); } $dbr->freeResult($res); echo "Done grabbing all titles from db at " . microtime(true) . "\n"; $articles = array(); $count = 0; //first check to see if there are more than 3 steps in the photo foreach ($titles as $id => $info) { $title = Title::newFromID($id); $revision = Revision::newFromTitle($title); $intro = Wikitext::getIntro($revision->getText()); $hasIntroImage = preg_match('@\\[\\[Image:([^\\]|]*)(\\|[^\\]]*)?\\]\\]@s', $intro); if (!$hasIntroImage) { $section = Wikitext::getStepsSection($revision->getText(), true); $num_step_photos = preg_match_all('@\\[\\[Image:([^\\]|]*)(\\|[^\\]]*)?\\]\\]@s', $section[0], $matches); if ($num_step_photos > 0) { $articles[] = $id; } } $count++; if ($count % 1000 == 0) { echo "Done processing " . $count . " artciles\n"; } } echo "Done processing all titles. Left with " . count($articles) . " titles. At " . microtime(true) . "\n"; $fo = fopen($argv[0], 'w'); fwrite($fo, "<html><head></head><body>"); //now that we have all the data, spit out the info foreach ($articles as $id) {
function getImageFromIntro($articleId, $revid = '') { global $wgMemc; $key = wfMemcKey("GallerySlide_getImageFromIntro", $articleId, $revid); $result = $wgMemc->get($key); if ($result) { return $result; } $dbr = wfGetDB(DB_SLAVE); $rev = Revision::loadFromPageId($dbr, $articleId); if ($rev) { $intro = Wikitext::getIntro($rev->getText()); if ($intro) { preg_match("@\\[\\[Image:[^\\]|\\|]*@", $intro, $results); $results = $results[0]; if ($revid != '') { $wgMemc->set($key, $results); } } } return $results; }
private function replaceSection($sectionName, $wikitext) { global $wgParser; $section = Wikitext::getSection($this->wikitext, $sectionName, true); if (empty($section[0])) { throw new Exception("Couldn't find '{$sectionName}' section"); } $newTxt = "== {$sectionName} ==\n" . $wikitext; $this->wikitext = $wgParser->replaceSection($this->wikitext, $section[1], $newTxt); }
function categorize($aid) { global $wgRequest; $t = Title::newFromId($aid); if ($t && $t->exists()) { $dbr = wfGetDB(DB_MASTER); $wikitext = Wikitext::getWikitext($dbr, $t); $intro = Wikitext::getIntro($wikitext); $intro = $this->stripCats($intro); $cats = array_reverse($wgRequest->getArray('cats', array())); $intro .= $this->getCatsWikiText($cats); $wikitext = Wikitext::replaceIntro($wikitext, $intro); $result = Wikitext::saveWikitext($t, $wikitext, 'categorization'); // Article saved successfully if ($result === '') { wfRunHooks("CategoryHelperSuccess", array()); } } }
function getPinterestImage($title, $fromPad = true) { global $wgLanguageCode, $wgContLang; if (in_array($title->getNamespace(), array(NS_MAIN, NS_CATEGORY))) { if ($title->getNamespace() == NS_MAIN) { $file = Wikitext::getTitleImage($title); if ($file && isset($file)) { $url = "/images/" . $file->getRel(); if ($fromPad) { $url = wfGetPad($url); } return $url; } } $catmap = Categoryhelper::getIconMap(); // still here? use default categoryimage // if page is a top category itself otherwise get top if (isset($catmap[urldecode($title->getPartialURL())])) { $cat = urldecode($title->getPartialURL()); } else { $cat = Categoryhelper::getTopCategory($title); //INTL: Get the partial URL for the top category if it exists // For some reason only the english site returns the partial URL for getTopCategory if (isset($cat) && $wgLanguageCode != 'en') { $title = Title::newFromText($cat); if ($title != null) { $cat = $title->getPartialURL(); } } } if (isset($catmap[$cat])) { $image = Title::newFromText($catmap[$cat]); $file = wfFindFile($image, false); if ($file) { $url = "/images/" . $file->getRel(); if ($fromPad) { $url = wfGetPad($url); } if ($url) { return $url; } } else { $url = "/skins/WikiHow/images/wikihow_large.jpg"; if ($fromPad) { $url = wfGetPad($url); } if ($url) { return $url; } } } else { $url = "/skins/WikiHow/images/wikihow_large.jpg"; if ($fromPad) { $url = wfGetPad($url); } if ($url) { return $url; } } } }
function revertTipOnArticle($pageId, $revId) { global $wgParser; // do not revert if no revId if ($revId <= 0 || $revId == null || $revId == "") { return false; } $undoRevision = Revision::newFromId($revId); $previousRevision = $undoRevision ? $undoRevision->getPrevious() : null; // do not revert if the page is wrong or changed.. if (is_null($undoRevision) || is_null($previousRevision) || $undoRevision->getPage() != $previousRevision->getPage() || $undoRevision->getPage() != $pageId) { return false; } $title = Title::newFromID($pageId); $article = new Article($title); $undoRevisionText = $undoRevision->getText(); $currentText = $article->getContent(); $undoTips = Wikitext::splitTips(reset(Wikitext::getSection($undoRevisionText, "Tips", true))); $prevTips = Wikitext::splitTips(reset(Wikitext::getSection($previousRevision->getText(), "Tips", true))); $currentTipsSection = Wikitext::getSection($currentText, "Tips", true); $currentTips = Wikitext::splitTips($currentTipsSection[0]); $section = $currentTipsSection[1]; $undoTipsFormatted = array(); foreach ($undoTips as $tip) { $undoTipsFormatted[] = self::cleanTip($tip); } $prevTipsFormatted = array(); foreach ($prevTips as $tip) { $prevTipsFormatted[] = self::cleanTip($tip); } $badTips = array_diff($undoTipsFormatted, $prevTipsFormatted); $resultTips = "== Tips =="; foreach ($currentTips as $currentTip) { $tip = self::cleanTip($currentTip); if (in_array($tip, $badTips)) { continue; } $resultTips .= "\n" . $currentTip; } $newText = $wgParser->replaceSection($currentText, $section, $resultTips); $success = $article->doEdit($newText, 'reverting tip from revision ' . $revId, EDIT_UPDATE | EDIT_MINOR); // mark the recent change as patrolled if ($success) { // should be ok to read from slave here because the change has been done earlier. $dbr = wfGetDB(DB_SLAVE); $rcid = $dbr->selectField('recentchanges', 'rc_id', array("rc_this_oldid={$revId}")); RecentChange::markPatrolled($rcid); PatrolLog::record($rcid, false); } return $success; }
private static function genTitle($title, $test, $custom) { $titleTxt = $title->getText(); $howto = wfMsg('howto', $titleTxt); list($wikitext, $stepsText) = self::getWikitext($title); switch ($test) { case self::TITLE_CUSTOM: // Custom $title = $custom; break; case self::TITLE_SITE_PREVIOUS: // How to XXX: N Steps (with Pictures) - wikiHow list($numSteps, $withPictures) = self::getTitleExtraInfo($wikitext, $stepsText, $test); $inner = $numSteps > 0 ? "{$howto}: {$numSteps} Steps" : $howto; $inner = $withPictures ? "{$inner} (with Pictures)" : $inner; $title = wfMsg('pagetitle', $inner); break; default: // How to XXX: N Steps (with Pictures) - wikiHow // From Chris's Mar 25 email // How to XXX: N Steps (with Pictures) - wikiHow // From Chris's Mar 25 email case 5: // default, but not "with Pictures" // default, but not "with Pictures" case 6: // n Tips on How to ... "with Pictures" // n Tips on How to ... "with Pictures" case 7: // n Tips on How to ... but not "with Pictures" // n Tips on How to ... but not "with Pictures" case 8: // How to ...: Step-by-Step Instructions "with Pictures" // How to ...: Step-by-Step Instructions "with Pictures" case 9: // How to ...: Step-by-Step Instructions but not "with Pictures" $methods = Wikitext::countAltMethods($stepsText); if ($methods >= 3) { $inner = "{$methods} Ways to {$titleTxt}"; $title = wfMsg('pagetitle', $inner); if (strlen($title) > self::MAX_TITLE_LENGTH) { $title = $inner; } } else { list($numSteps, $withPictures) = self::getTitleExtraInfo($wikitext, $stepsText, $test); $forceNoWithPictures = in_array($test, array(5, 7, 9)); $withPictures = !$forceNoWithPictures ? $withPictures : false; if ($test == 6 || $test == 7) { $inner = $numSteps > 0 ? "{$numSteps} Tips on {$howto}" : $howto; } elseif ($test == 8 || $test == 9) { $inner = $numSteps > 0 ? "{$howto}: Step-by-Step Instructions" : $howto; } else { $inner = $numSteps > 0 ? "{$howto}: {$numSteps} Steps" : $howto; } $inner = $withPictures ? "{$inner} (with Pictures)" : $inner; $title = wfMsg('pagetitle', $inner); // first, try articlename + metadata + wikihow if (strlen($title) > self::MAX_TITLE_LENGTH) { // next, try articlename + metadata $title = $inner; if ($numSteps > 0 && strlen($title) > self::MAX_TITLE_LENGTH) { // next, try articlename + steps if ($test == 6 || $test == 7) { $inner = "{$numSteps} Tips on {$howto}"; } elseif ($test == 8 || $test == 9) { $inner = "{$howto}: Step-by-Step Instructions"; } else { $title = "{$howto}: {$numSteps} Steps"; } } if (strlen($title) > self::MAX_TITLE_LENGTH) { // next, try articlename + wikihow $title = wfMsg('pagetitle', $howto); if (strlen($title) > self::MAX_TITLE_LENGTH) { // lastly, set title just as articlename $title = $howto; } } } } break; // start of new Title Tests from Chris's March 29 email //case 12: // How to XXX: N Tips - wikiHow //case 13: // N Tips on How to XXX - wikiHow //case 14: // How to XXX: Step-by-Step Instructions //case 15: // How to XXX: N Methods - wikiHow //case 16: // N Ways to XXX - wikiHow //case 17: // How to XXX with Step-by-Step Pictures // start of new title tests from Chris's Oct 2 email /*case 18: // How to XXX with Step-by-Step Pictures $inner = ''; $methods = Wikitext::countAltMethods($stepsText); if ($methods >= 4) { $inner = "$methods Ways to $titleTxt"; } else { $steps = Wikitext::countSteps($stepsText); if (3 <= $steps && $steps < 15) { $inner = "$steps Tips on $howto"; } } if (!$inner) { $inner = "$howto: Step-by-Step Instructions"; } $title = wfMsg('pagetitle', $inner); if (strlen($title) > self::MAX_TITLE_LENGTH) { $title = $inner; } break;*/ } return $title; }
/** * The process of adding and removing all articles from the randomizer * set. * * @param int $from unix timestamp indicates from when to process. 0 * means the epoch. */ private static function processArticles($from) { $dbr = wfGetDB(DB_SLAVE); $articles = self::loadArticles($dbr, $from); foreach ($articles as &$article) { $pr = array('pr_id' => $article['page_id'], 'pr_namespace' => NS_MAIN, 'pr_title' => $article['page_title'], 'pr_random' => wfRandom(), 'pr_catinfo' => $article['page_catinfo'], 'pr_updated' => wfTimestampNow()); $article = $pr; } $featured = self::loadFeaturedArticles($dbr); $rising = self::loadRisingStars($dbr); $views = self::loadHighViews($dbr); $edits = self::loadHighEdits($dbr); $rated = self::loadHighlyRated($dbr); $add = array(); $remove = array(); $reasons = array(); foreach ($articles as $i => $article) { //print "{$article['pr_title']}\n"; $reason = array(); $toadd = true; $id = $article['pr_id']; $title = Title::newFromDBkey($article['pr_title']); if (!$title) { $toadd = false; $reason[] = 'does-not-exist'; $wikitext = ''; } else { $wikitext = self::getWikitext($dbr, $title); if (!$wikitext) { $toadd = false; $reason[] = 'does-not-exist'; } } if ($wikitext) { $intro = Wikitext::getIntro($wikitext); list($steps, ) = Wikitext::getStepsSection($wikitext); if (self::excludeViaTemplates($intro)) { $reason[] = 'excluded-via-template'; $toadd = false; } else { $images = self::getNumStepsImages($steps); if (isset($featured[$id])) { $reason[] = 'featured'; } if ($images && isset($rising[$id])) { $reason[] = 'rising'; } if ($images && isset($rated[$id])) { $reason[] = 'highly-rated'; } if ($images && isset($views[$id]) && isset($edits[$id])) { $reason[] = 'views-and-edits'; } if ($images && self::hasAlternateMethods($steps)) { $reason[] = 'views-and-alternate-methods'; } if ($images && isset($views[$id]) && self::getNumSteps($steps) >= 9) { $reason[] = 'views-and-nine-steps'; } if (self::getNumStepsImages($steps) >= 3) { $reason[] = 'three-steps-images'; } if ($images && isset($views[$id]) && self::hasVideo($wikitext)) { $reason[] = 'views-and-video'; } if (empty($reason)) { $reason[] = 'no-match'; $toadd = false; } } } if ($toadd) { $add[] = $article; } else { $remove[] = $article; } $reasons[] = array('dprr_id' => $id, 'dprr_namespace' => NS_MAIN, 'dprr_title' => substr($article['pr_title'], 0, 255), 'dprr_reasons' => substr(join(',', $reason), 0, 255)); } $dbw = wfGetDB(DB_MASTER); if (!$from) { // do this right before we insert a bunch of new rows self::dbClearRandomizer($dbw); } else { self::dbSaveRandom($dbw, $remove, false); } self::dbSaveRandom($dbw, $add, true); self::dbReplaceReasons($dbw, $reasons); }