--- a/busui/owa/mw_plugin.php +++ b/busui/owa/mw_plugin.php @@ -1,1 +1,544 @@ + 'Open Web Analytics for MediaWiki', + 'author' => 'Peter Adams', + 'url' => 'http://www.openwebanalytics.com', + 'description' => 'Open Web Analytics for MedaWiki' +); + +// used to sniff out admin requests +$wgHooks['UnknownAction'][] = 'owa_actions'; +// used to set proper params for logging Article Page Views +$wgHooks['ArticlePageDataAfter'][] = 'owa_logArticle'; +// used to set proper params for logging Special Page Views +$wgHooks['SpecialPageExecuteAfterPage'][] = 'owa_logSpecialPage'; +// used to set proper params for logging Category Page Views +$wgHooks['CategoryPageView'][] = 'owa_logCategoryPage'; +// used to add OWA's javascript tracking tag to all pages +$wgHooks['BeforePageDisplay'][] = 'owa_footer'; +// used to fire Action events when articles are created +$wgHooks['ArticleInsertComplete'][] = 'owa_newArticleAction'; +// used to fire Action events when articles are edited +$wgHooks['ArticleSaveComplete'][] = 'owa_editArticleAction'; +// used to fire Action events when new articles are deleted +$wgHooks['ArticleDeleteComplete'][] = 'owa_deleteArticleAction'; +// used to fire Action events when new user accounts are created +$wgHooks['AddNewAccount'][] = 'owa_addUserAction'; +// used to fire Action events when new uploads occur +$wgHooks['UploadComplete'][] = 'owa_addUploadAction'; +// used to fire Action events when users login +$wgHooks['UserLoginComplete'][] = 'owa_userLoginAction'; +// used to fire Action events when talk pages are edited +$wgHooks['ArticleEditUpdateNewTalk'][] ='owa_editTalkPageAction'; +// used to register OWA's special page +$wgHooks['SpecialPage_initList'][] = 'owa_registerSpecialPage'; + +/** + * Hook Function for Registering OWA's Special Page + */ +function owa_registerSpecialPage( &$aSpecialPages ) { + + global $wgOwaEnableSpecialPage; + + // Enable Special Page + if ( $wgOwaEnableSpecialPage === true ) { + //Load Special Page + $wgAutoloadClasses['SpecialOwa'] = __FILE__; + // Adds OWA's admin interface to special page list + $aSpecialPages['Owa'] = 'SpecialOwa'; + } + // must return true for hook to continue processing. + return true; +} + +/** + * Hook for OWA special actions + * + * This uses mediawiki's 'unknown action' hook to trigger OWA's special action handler. + * This is setup by adding 'action=owa' to the URLs for special actions. There is + * probably a better way to do this so that the OWA namespace is preserved. + * + * @TODO figure out how to register this method to be triggered only when 'action=owa' instead of + * for all unknown mediawiki actions. + * @param object $specialPage + * @url http://www.mediawiki.org/wiki/Manual:MediaWiki_hooks/UnknownAction + * @return false + */ +function owa_actions($action) { + + global $wgOut, $wgUser, $wgRequest; + + $action = $wgRequest->getText( 'action' ); + if ( $action === 'owa' ) { + $wgOut->disable(); + $owa = owa_singleton(); + $owa->handleSpecialActionRequest(); + return false; + } else { + return true; + } +} + +/** + * OWA Singelton + * + * Needed to avoid OWA loading for every mediawiki request + */ +function owa_singleton() { + + static $owa; + + if ( empty( $owa ) ) { + + global $wgUser, + $wgServer, + $wgScriptPath, + $wgScript, + $wgMainCacheType, + $wgMemCachedServers, + $wgOwaSiteId, + $wgOwaMemCachedServers; + + /* OWA CONFIGURATION OVERRIDES */ + $owa_config = array(); + // check for memcache. these need to be passed into OWA to avoid race condition. + if ( $wgMainCacheType === CACHE_MEMCACHED ) { + $owa_config['cacheType'] = 'memcached'; + $owa_config['memcachedServers'] = $wgMemCachedServers; + } + $owa = new owa_mw( $owa_config ); + $owa->setSetting( 'base', 'report_wrapper', 'wrapper_mediawiki.tpl' ); + $owa->setSetting( 'base', 'main_url', $wgScriptPath.'/index.php?title=Special:Owa' ); + $owa->setSetting( 'base', 'main_absolute_url', $wgServer.$owa->getSetting( 'base', 'main_url' ) ); + $owa->setSetting( 'base', 'action_url', $wgServer.$wgScriptPath.'/index.php?action=owa&owa_specialAction' ); + $owa->setSetting( 'base', 'api_url', $wgServer.$wgScriptPath.'/index.php?action=owa&owa_apiAction' ); + $owa->setSetting( 'base', 'link_template', '%s&%s' ); + $owa->setSetting( 'base', 'is_embedded', true ); + $owa->setSetting( 'base', 'query_string_filters', 'returnto' ); + $owa->setSetting( 'base', 'delay_first_hit', false ); + + if ( ! $wgOwaSiteId ) { + $wgOwaSiteId = md5($wgServer.$wgScriptPath); + } + + $owa->setSiteId( $wgOwaSiteId ); + /** + * Populates OWA's current user object with info about the current mediawiki user. + * This info is needed by OWA authentication system as well as to add dimensions + * requests that are logged. + */ + $cu = &owa_coreAPI::getCurrentUser(); + $cu->setUserData( 'user_id', $wgUser->getName() ); + $cu->setUserData( 'email_address', $wgUser->getEmail() ); + $cu->setUserData( 'real_name', $wgUser->getRealName() ); + $cu->setRole( owa_translate_role( $wgUser->getGroups() ) ); + $cu->setAuthStatus(true); + } + + return $owa; +} + +/** + * Transalates MW Roles into OWA Roles + * + * @todo make this configurable with a global property + */ +function owa_translate_role($level = array()) { + + if ( ! empty( $level ) ) { + + if ( in_array( "*", $level ) ) { + $owa_role = 'everyone'; + } elseif ( in_array( "user", $level ) ) { + $owa_role = 'viewer'; + } elseif ( in_array( "autoconfirmed", $level ) ) { + $owa_role = 'viewer'; + } elseif ( in_array( "emailconfirmed", $level ) ) { + $owa_role = 'viewer'; + } elseif ( in_array( "bot", $level ) ) { + $owa_role = 'viewer'; + } elseif ( in_array( "sysop", $level ) ) { + $owa_role = 'admin'; + } elseif ( in_array( "bureaucrat", $level ) ) { + $owa_role = 'admin'; + } elseif ( in_array( "developer", $level ) ) { + $owa_role = 'admin'; + } + + } else { + $owa_role = ''; + } + + return $owa_role; +} + +/** + * Helper function for tracking page views of various types + */ +function owa_trackPageView( $params = array() ) { + + global $wgUser, $wgOut, $wgOwaSiteId; + + $owa = owa_singleton(); + + if ( $owa->getSetting( 'base', 'install_complete' ) ) { + + //$event = $owa->makeEvent(); + //$event->setEventType( 'base.page_request' ); + $owa->setSiteId( $wgOwaSiteId ); + $owa->setProperty( 'user_name', $wgUser->mName ); + $owa->setProperty( 'user_email', $wgUser->mEmail ); + $owa->setProperty( 'language', owa_getLanguage() ); + if ( ! $owa->pageview_event->get( 'page_type') ) { + $owa->setPageType( '(not set)' ); + } + + //foreach ( $params as $k => $v ) { + // $event->set( $k, $v ); + //} + + // if the page title is not set for some reasons, set it + // using $wgOut. + if ( ! $owa->pageview_event->get( 'page_title') ) { + $owa->setPageTitle( 'page_title', $wgOut->getPageTitle() ); + } + + /* + $tag = sprintf( + ' + var owa_params = %s;', + json_encode( $event->getProperties() ) + ); + + $wgOut->addInlineScript( $tag ); + */ + } + + return true; +} + +/** + * Logs Special Page Views + * + * @param object $specialPage + * @return boolean + */ +function owa_logSpecialPage(&$specialPage) { + + $title_obj = $specialPage->getTitle(); + $title = $title_obj->getText(); + $owa = owa_singleton(); + $owa->setPageTitle( $title ); + $owa->setPageType( 'Special Page' ); + return true; +} + +/** + * Logs Category Page Views + * + * @param object $categoryPage + * @return boolean + */ +function owa_logCategoryPage( &$categoryPage ) { + + $title_obj = $categoryPage->getTitle(); + $title = $title_obj->getText(); + $owa = owa_singleton(); + $owa->setPageTitle( $title ); + $owa->setPageType( 'Category' ); + return true; +} + +/** + * Logs Article Page Views + * + * @param object $article + * @return boolean + */ +function owa_logArticle( &$article ) { + + $title_obj = $article->getTitle(); + $title = $title_obj->getText(); + $owa = owa_singleton(); + $owa->setPageTitle( $title ); + $owa->setPageType( 'Article' ); + return true; +} + +/** + * Helper Function for tracking Action Events + * + * This function is a wrapper for the Action Event API in owa_client. + * + * @param $action_name string The name of the action being tracked + * @param $label string The label associated with the action being tracked + * @return boolean true + */ +function owa_trackAction( $action_name, $label ) { + + $owa = owa_singleton(); + + if ( $owa->getSetting( 'base', 'install_complete' ) ) { + $owa->trackAction( 'mediawiki', $action_name, $label ); + owa_coreAPI::debug( "logging action event " . $action_name ); + } + + return true; +} + +/** + * Logs New Articles + * + * @param object $categoryPage + * @return boolean + */ +function owa_newArticleAction(&$article, &$user, $text, $summary, $minoredit, &$watchthis, $sectionanchor, &$flags, $revision) { + + $label = $article->getTitle()->getText(); + return owa_trackAction( 'Article Created', $label ); +} + +function owa_editArticleAction($article, &$user, $text, $summary, + $minoredit, &$watchthis, $sectionanchor, &$flags, $revision, + &$status, $baseRevId, &$redirect = '') { + + if ( $flags & EDIT_UPDATE ) { + + $label = $article->getTitle()->getText(); + return owa_trackAction( 'Article Edit', $label ); + + } else { + + return true; + } +} + +function owa_deleteArticleAction( &$article, &$user, $reason, $id ) { + + $label = $article->getTitle()->getText(); + return owa_trackAction( 'Article Deleted', $label ); +} + +function owa_addUserAction( $user, $byEmail ) { + + $label = ''; + return owa_trackAction( 'User Account Added', $label ); +} + +function owa_addUploadAction( &$image ) { + + $label = $image->getLocalFile()->getMimeType(); + return owa_trackAction( 'File Upload', $label ); +} + +function owa_userLoginAction( &$user, &$inject_html ) { + + $label = ''; + return owa_trackAction( 'Login', $label ); +} + +function editTalkPageAction( $article ) { + + $label = $article->getTitle()->getText(); + return owa_trackAction( 'Talk Page Edit', $label ); +} + +/** + * Adds javascript tracker to pages + * + * @param object $article + * @return boolean + */ +function owa_footer(&$wgOut, $sk) { + + global $wgRequest, $wgOwaThirdPartyCookies; + + if ($wgRequest->getVal('action') != 'edit' && $wgRequest->getVal('title') != 'Special:Owa') { + + $owa = owa_singleton(); + if ($owa->getSetting('base', 'install_complete')) { + + $cmds = ""; + if ( $wgOwaThirdPartyCookies ) { + $cmds .= "owa_cmds.push( ['setOption', 'thirdParty', true] );"; + } + + if ( $wgOwaCookieDomain ) { + $cmds .= "owa_cmds.push( ['setCookieDomain', '$wgOwaCookieDomain'] );"; + } + + $page_properties = $owa->getAllEventProperties($owa->pageview_event); + if ( $page_properties ) { + $page_properties_json = json_encode( $page_properties ); + $cmds .= "owa_cmds.push( ['setPageProperties', $page_properties_json] );"; + } + + //$wgOut->addInlineScript( $cmds ); + + $options = array( 'cmds' => $cmds ); + + $tags = $owa->placeHelperPageTags(false, $options); + $wgOut->addHTML($tags); + + } + } + + return true; +} + +/** + * Gets mediawiki Language variable + */ +function owa_getLanguage() { + + global $wgLang, $wgContLang; + $code = ''; + + $code = $wgLang->getCode(); + if ( ! $code ) { + $code = $wgContLang->getCode(); + } + + return $code; +} + +/** + * OWA Special Page Class + * + * Enables OWA to be accessed through a Mediawiki special page. + */ +class SpecialOwa extends SpecialPage { + + function __construct() { + parent::__construct('Owa'); + self::loadMessages(); + } + + function execute() { + + global $wgRequest, $wgOut, $wgUser, $wgSitename, $wgScriptPath, $wgScript, $wgServer, + $wgDBtype, $wgDBname, $wgDBserver, $wgDBuser, $wgDBpassword; + + $this->setHeaders(); + //must be called after setHeaders for some reason or elsethe wgUser object is not yet populated. + $owa = owa_singleton(); + $params = array(); + + // if no action is found... + $do = owa_coreAPI::getRequestParam('do'); + if (empty($do)) { + // check to see that owa in installed. + if (!$owa->getSetting('base', 'install_complete')) { + + define('OWA_INSTALLING', true); + + $site_url = $wgServer.$wgScriptPath; + + $params = array( + 'site_id' => md5($site_url), + 'name' => $wgSitename, + 'domain' => $site_url, + 'description' => '', + 'do' => 'base.installStartEmbedded'); + + $params['db_type'] = $wgDBtype; + $params['db_name'] = $wgDBname; + $params['db_host'] = $wgDBserver; + $params['db_user'] = $wgDBuser; + $params['db_password'] = $wgDBpassword; + $params['public_url'] = $wgServer.$wgScriptPath.'/extensions/owa/'; + $page = $owa->handleRequest($params); + + // send to daashboard + } else { + $params['do'] = 'base.reportDashboard'; + $page = $owa->handleRequest($params); + } + // do action found on url + } else { + $page = $owa->handleRequestFromURL(); + } + + return $wgOut->addHTML($page); + + } + + function loadMessages() { + static $messagesLoaded = false; + global $wgMessageCache; + + if ( $messagesLoaded ) return; + + $messagesLoaded = true; + + // this should be the only msg defined by mediawiki + $allMessages = array( + 'en' => array( + 'owa' => 'Open Web Analytics' + ) + ); + + + // load msgs in to mediawiki cache + foreach ( $allMessages as $lang => $langMessages ) { + $wgMessageCache->addMessages( $langMessages, $lang ); + } + + return true; + } +} + +?>