User:Zayoo/Extension:Advanced Meta Code
Appearance
From mediawiki.org
***THIS PAGE IS NO LONGER VALID***
Changes has been updated to Extension:Advanced Meta and this page no longer updates.
Code
[edit ]<?php /* SQL to create required table: CREATE TABLE IF NOT EXISTS `mw_ext_meta` ( -- replace "mw" with your prefix `pageid` int(8) NOT NULL, `rindex` tinyint(1) NOT NULL, `rfollow` tinyint(1) NOT NULL, `titlealias` varchar(255), `keywords` varchar(500), `description` varchar(2000), PRIMARY KEY (`pageid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; */ /** * MediaWiki Advanced Meta extension * Add meta data to individual pages or entire namespaces * @version 1.4.0 * @author Stephan Muller <mail@litso.com> (Main author) * @author Bart van Heukelom <b@rtvh.nl> (Objectification) * @author Zayoo <zayoo@126.com> (Revise & TitleAlias, refer to Extension:Add HTML Meta and Title & Extension:TitleAlias) */ $wgExtensionCredits['parserhook'][] = array( 'name' => 'Advanced Meta', 'author' => 'Stephan Muller, Bart van Heukelom, Zayoo', 'descriptionmsg' => 'ameta-desc', 'url' => 'http://www.mediawiki.org/wiki/Extension:Advanced_Meta', 'version' => '1.4.0' ); $wgExtensionMessagesFiles['Advanced Meta'] = dirname(__FILE__) . '/MWAdvancedMeta.i18n.php'; MWAdvancedMeta::setup(); class MWAdvancedMeta { private static $instance = null; /** * Initialise the advanced meta plugin. * @return MWAdvancedMeta the plugin object, which you can use to set settings. */ public static function setup() { // check for wiki if (!defined('MEDIAWIKI')) { throw new Exception('This is an extension to the MediaWiki software and cannot be used standalone.'); } // create plugin if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } private $indexedPages = array(NS_MAIN, NS_PROJECT); private $globalKeywords = array(); private $allowedUsers = array(); private $allowedUsergroups = array('sysop', 'bureaucrat'); private $savedMeta = null; public function __construct() { /********* * Hooks * *********/ global $wgHooks; //Inserts HTML for meta input fields into the edit page. $wgHooks['ParserBeforeTidy'][] = $this; //Before the updated text and properties of an article are saved to the database //the new meta info is saved too $wgHooks['ArticleSave'][] = $this; //If a new article is created the meta is temporarily saved as article ID '0' //Move it to the newly created article now $wgHooks['ArticleInsertComplete'][] = $this; //Insert meta into article $wgHooks['OutputPageBeforeHTML'][] = $this; //Title Alias $wgHooks['BeforePageDisplay'][] = $this; } /** * All namespaces get a robots setting of "noindex, nofollow" by default. * Use this method to specify namespaces with interesting content, pages in which should be indexed. * Default is NS_MAIN and NS_PROJECT. * @param $indexedPages Array of namespace names. */ public function setIndexedPages(array $indexedPages) { $this->indexedPages = $indexedPages; } /** * Specify keywords that should be added to every page. * @param $keywords The keywords in an array. */ public function setGlobalKeywords($keywords) { $this->globalKeywords = $keywords; } /** * SEO can be a delicate issue. Define here who is allowed to edit the meta tags * allow users individually, by username. Warning: Case sensitive! */ public function setAllowedUsers($users) { $this->allowedUsers = $users; } /** * allow users by mediawiki's own usergroups * or the special groups 'loggedin' and 'all' ('all' allowing even anonymous edits) */ public function setAllowedUsergroups($usergroups) { $this->allowedUsergroups = $usergroups; } /********* * Hooks * *********/ /** * Hook 1: in /includes/parser/Parser.php * Loops through the different sections of the page being parsed * and adds html for the meta input forms into the article edit pages * * @param object $parser The parser object * @param string $text * * @global indexedpages defined in the global config section above * @global alloweusers defined in the global config section above * * @return true * */ public function onParserBeforeTidy(&$parser, &$text) { $fname = 'MWAdvancedMeta::onParserBeforeTidy'; global $wgTitle, $wgUser, $wgRequest; // only run this hook for edit forms if(!$wgRequest->getVal('action') == ('edit' || 'submit')) return false; // can this user edit meta for this page? if(!$this->canEditMeta()) return false; // handle submit (preview) if ($wgRequest->wasPosted()) { // it's probably a preview, so show the newly submitted meta too, otherwise we'll lose 'em $meta = array( 'rindex' => (isset($_POST['wpIndex'])) ? '1' : '0', 'rfollow' => (isset($_POST['wpFollow'])) ? '1' : '0', 'titlealias' => $_POST['wpTitleAlias'], 'keywords' => $_POST['wpKeywords'], 'description' => $_POST['wpDescription'] ); } else { // else just get the meta from the db $meta = $this->getMetaByArticleID($wgTitle->getArticleID()); // no meta or creating a new article? make default values if(empty($meta) || $wgTitle->getArticleID() == '0') { $meta = array( 'rindex' => '1', 'rfollow' => '1', 'titlealias' => '', 'keywords' => '', 'description' => '' ); } } // prepare checkboxes $checkindex = ($meta['rindex'] == '1') ? 'checked="checked"' : '' ; $checkfollow = ($meta['rfollow'] == '1') ? 'checked="checked"' : '' ; // some mediawiki preference variables $cols = $wgUser->getIntOption('cols'); $ew = $wgUser->getOption('editwidth'); $hidden = ""; //don't know when this is exactly used. If I find out, I'll do something with it :) /*$addedkeywords = count($this->globalKeywords) == 0 ? '(none)' : implode(', ', $this->globalKeywords); */ $addedkeywords = wfMsg( 'globalkeywords' )=='<globalkeywords>' ? '(none)' : wfMsg( 'globalkeywords' ); // define replacements $replaceFrom[] = '<div id="editpage-copywarn">'; $replaceWith[] = "<h2>" . wfMsg( 'ameta-metasettings' ) . "</h2> <strong>Robots:</strong> <label><input tabindex='2' id='wpIndex' type='checkbox' name='wpIndex' value='1' {$checkindex} accesskey='/'> Index</label> <label><input tabindex='3' id='wpFollow' type='checkbox' name='wpFollow' value='1' {$checkfollow} > Follow</label> <br /><strong>" . wfMsg( 'ameta-titlealias' ) . "</strong><br /> <input type='text' name='wpTitleAlias' id='wpTitleAlias' value='{$meta['titlealias']}' size='64'> <br /><strong>Keywords:</strong> <small>" . wfMsg( 'ameta-keywordsadd' ) . "<a href='javascript:;' title='" . wfMsg( 'ameta-keywordsmodify' ) . "'>" . htmlspecialchars(str_replace("1ドル",$wgTitle,$addedkeywords))."</a> </small><br /> <textarea tabindex='4' name='wpKeywords' id='wpKeywords' rows='1' cols='{$cols}'{$ew}{$hidden}>{$meta['keywords']}</textarea> <br /><strong>Description:</strong><br /> <textarea tabindex='4' name='wpDescription' id='wpDescription' rows='2' cols='{$cols}'{$ew}{$hidden}>{$meta['description']}</textarea> <div id=\"editpage-copywarn\">"; // apply replacements $text = str_replace($replaceFrom, $replaceWith, $text); return true; } /** * Hook 2: Called during function doEdit() in /includes/Article.php * Adds the new meta information to the database when an article is saved * * @param object $article The entire article and it's properties * @param object $user The user updating the article * @return true * * @global indexedpages, array of namespaces that should be indexed * */ public function onArticleSave(&$article, &$user) { $fname = 'MWAdvancedMeta::onArticleSave'; $id = $article->mTitle->getArticleID(); //can this user edit meta for this page? if (!$this->canEditMeta()) return true; //return false gives edit conflicts // get meta from the posted forms $metaData = array( 'rindex' => isset($_POST['wpIndex']) ? '1' : '0', 'rfollow' => isset($_POST['wpFollow']) ? '1' : '0', 'titlealias' => htmlspecialchars($_POST['wpTitleAlias']), 'keywords' => htmlspecialchars($_POST['wpKeywords']), 'description' => htmlspecialchars($_POST['wpDescription']) ); if ($id == 0) { // if this is an insert, we need to store the meta until we know the page id $this->savedMeta = $metaData; } else { // write new metadata to the database $this->writeMeta($id, $metaData); } // empty cache for the page $dbw = wfGetDB( DB_MASTER ); $timestamp = $dbw->timestamp(); $dbw->update( 'page', array( 'page_touched' => $timestamp ), array( 'page_id' => $id ), $fname ); return true; } /** * Hook 3: Called during function doEdit() in /includes/Article.php * Move the new meta information from a temporary id='0' to the new article's id * * @param object $article: the article (object) saved * @param object $user: the user (object) who saved the article * @param string $text: the new article content * @param string $summary: the article summary (comment) * @param bool $minoredit: minor edit flag * @param bool $watchthis: not used as of 1.8 (automatically set to "null") * @param bool $sectionanchor: not used as of 1.8 (automatically set to "null") * @param unknown $flags: bitfield, see source code for details; passed to Article::doedit() * @param object $revision: The newly inserted revision object (as of 1.11.0) * @return true * * @global indexedpages, array of namespaces that should be indexed * */ function onArticleInsertComplete(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision) { $fname = 'MWAdvancedMeta::onArticleInsertComplete'; // if we have saved metadata, insert it if($this->savedMeta !== null) { // write new metadata to the database $this->writeMeta($article->getID(), $this->savedMeta); $this->savedMeta = null; } return true; } /** * Hook 4: Called during function view() in /includes/OutputPage.php * Adds the proper meta tags to the article when a page is viewed * * @param object $out The outputted page * @param string $text The file description * @return true */ function onOutputPageBeforeHTML(&$out, &$text) { global $wgTitle; $fname = 'MWAdvancedMeta::onOutputPageBeforeHTML'; $addedkeywords = wfMsg( 'globalkeywords' )=='<globalkeywords>' ? '' : wfMsg( 'globalkeywords' , $wgTitle); // pages that aren't in the array indexedpages won't be indexed, but links will be followed if (!in_array($wgTitle->getnamespace(), $this->indexedPages)) { $out->setRobotPolicy('noindex, follow'); } else { $out->setRobotPolicy('index, follow'); } // for indexed namespaces, get the info from the db $meta = $this->getMetaByArticleID($wgTitle->getArticleID()); // nothing in db? use global keywords other than exit now if (empty($meta)) { $out->mKeywords = array_merge(explode(',',$addedkeywords), $out->mKeywords); //Global keywords should be shown even no meta data return false; } // set the keywords // only overwrite keywords if any were provided (else the ones generated by mediawiki are used) if (!empty($meta['keywords'])) { $out->mKeywords = array_merge(explode(',',$addedkeywords), explode(',', $meta['keywords'])); } else { $out->mKeywords = array_merge(explode(',',$addedkeywords), $out->mKeywords); } // set the description if(!empty($meta['description'])) $out->addMeta("description", $meta['description']); // set robots information $index = ($meta['rindex'] == '1') ? 'index' : 'noindex'; $follow = ($meta['rfollow'] == '1') ? 'follow' : 'nofollow'; $out->setRobotPolicy($index.', '.$follow); return true; } /** * Hook 5: Called during function output() in /includes/OutputPage.php * Allows last minute changes to the output page, e.g. adding of CSS or Javascript by extensions * * @param object $out The OutputPage object * @param string $sk Skin object that will be used to generate the page * @return true */ function onBeforePageDisplay(&$out, &$text) { global $wgTitle; $fname = 'MWAdvancedMeta::onBeforePageDisplay'; $meta = $this->getMetaByArticleID($wgTitle->getArticleID()); if (empty($meta)) return true; if (!empty($meta['titlealias'])) $out->mHTMLtitle=wfMsg( 'pagetitle', $meta['titlealias'] ); return true; } /************* * Functions * *************/ private function getMetaByArticleID($id) { $fname = 'MWAdvancedMeta::getMetaByArticleID'; // get metadata from database $dbr = wfGetDB( DB_MASTER ); $data = $dbr->select( 'ext_meta', array( 'rindex', 'rfollow', 'titlealias', 'keywords', 'description' ), array( 'pageid' => $id ), $fname ); $meta = $dbr->fetchRow( $data ); $dbr->freeResult($data); return $meta; } private function writeMeta($id, $metaData) { $fname = 'MWAdvancedMeta::writeMeta'; $dbw = wfGetDB( DB_MASTER ); if($metaData['rindex']=='1'&&$metaData['rfollow']=='1'&&empty($metaData['titlealias'])&&empty($metaData['keywords'])&&empty($metaData['description'])) { $dbw->delete( 'ext_meta', array( 'pageid' => $id ), __METHOD__ ); //delete meta with normal robot policies and without titlealias, keywords & description to save space } else { $dbw->replace( 'ext_meta', array( 'pageid' => $id), array_merge($metaData, array('pageid' => $id)), $fname ); } } private function canEditMeta() { global $wgUser, $wgTitle; $fname = 'MWAdvancedMeta::canEditMeta'; $ns = $wgTitle->getNamespace(); // redirect pages don't need metadata // TODO: make work in MediaWiki < 1.13 // if ($wgTitle->isRedirect()) { // return false; // } // does the user have permission? return (in_array($wgUser->getName(), $this->allowedUsers) || in_array('all', $this->allowedUsergroups) || (in_array('loggedin', $this->allowedUsergroups) && $wgUser->isLoggedIn()) || count(array_intersect($wgUser->getGroups(), $this->allowedUsergroups)) !== 0 ); } }