/** * Initializes required fields. */ private function initFields() { if ($this->oUser === null) { throw new BsException(__METHOD__ . ' - No user specified.'); } $this->sUserDisplayName = BsCore::getInstance()->getUserDisplayName($this->oUser); $sUserImage = $this->oUser->getOption('MW::UserImage', ''); //BsConfig::get() won't work on first call //Is it a URL? Some external image? $aParsedUrl = parse_url($sUserImage); if (!empty($sUserImage) && ($sUserImage[0] == '/' || isset($aParsedUrl['scheme']))) { $this->sImageUploadPath = SpecialPage::getTitleFor('Preferences')->getLinkUrl(); $aPathInfo = pathinfo($aParsedUrl['path']); $aFileExtWhitelist = array('gif', 'jpg', 'jpeg', 'png'); $this->sImagePath = $aParsedUrl['scheme'] . '://' . $aParsedUrl['host'] . $aParsedUrl['path']; if (!in_array(strtolower($aPathInfo['extension']), $aFileExtWhitelist)) { $this->sImagePath = BsConfig::get('MW::AnonUserImage'); } return; } $oUserImageFile = RepoGroup::singleton()->getLocalRepo()->newFile($sUserImage); if ($oUserImageFile) { $UserImageArticle = new ImagePage($oUserImageFile->getTitle()); $this->sImageUploadPath = $UserImageArticle->getUploadUrl(); if ($oUserImageFile->exists() === false) { $this->sImagePath = BsConfig::get('MW::DefaultUserImage'); } else { $oUserThumbnail = $oUserImageFile->transform(array('width' => 64, 'height' => 64)); if ($oUserThumbnail !== false) { $this->sImagePath = $oUserThumbnail->getUrl(); } else { $this->sImagePath = $oUserImageFile->getUrl(); } } } else { $this->sImagePath = BsConfig::get('MW::DefaultUserImage'); } }
/** * Renders the body of a blog item * @return string Rendered HTML */ protected function renderArticle() { $sOut = '__NOTOC__ __NOEDITSECTION__'; if ($this->getOption('showInfo')) { if ($this->mAuthorPage) { $sAuthorUserPageWikiLink = '[[' . $this->mAuthorPage . '|' . $this->mAuthorName . ']]'; } else { $sAuthorUserPageWikiLink = $this->mAuthorName; } $sOut .= "\n" . '<div class="bs-blog-item-info">' . $this->mEntryDate . ' - ' . $sAuthorUserPageWikiLink . '</div>' . "\n"; } $sOut .= "\n"; $sOut .= $this->mContent; if ($this->getOption('moreAtEndOfEntry')) { $sOut .= ' '; } else { $sOut .= "\n"; } $sParsedOut = BsCore::getInstance()->parseWikiText($sOut, RequestContext::getMain()->getTitle()); $sOut = $sParsedOut; if ($this->getOption('more')) { $aLinkOptions = array('href' => $this->mUrl, 'class' => 'bs-blog-item-read-more', 'title' => wfMessage('bs-blog-read-more')->plain()); if ($this->getOption('moreInNewWindow')) { $aLinkOptions['openInNewWindow'] = true; } $sContent = wfMessage('bs-blog-read-more')->plain(); if ($this->getOption('moreAtEndOfEntry')) { $sContent .= '...'; } $sOut .= $this->renderLink($aLinkOptions, $sContent); if (!$this->getOption('moreAtEndOfEntry')) { $sOut .= $this->mActionDivisor; } else { $sOut .= '<br />'; } } return $sOut; }
private function getAuthorsViewForAfterContent($oSkin, &$aDetails) { $oTitle = $oSkin->getTitle(); //Read in config variables $iLimit = BsConfig::get('MW::Authors::Limit'); $aBlacklist = BsConfig::get('MW::Authors::Blacklist'); $sMoreImage = BsConfig::get('MW::Authors::MoreImage'); $aParams = array(); $aParams['width'] = BsConfig::get('MW::Authors::ImageWidth'); $aParams['height'] = BsConfig::get('MW::Authors::ImageHeight'); $sPrintable = $oSkin->getRequest()->getVal('printable', 'no'); $iArticleId = $oTitle->getArticleID(); $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'Authors', $iArticleId); $aData = BsCacheHelper::get($sKey); if ($aData !== false) { wfDebugLog('BsMemcached', __CLASS__ . ': Fetched AuthorsView and Details from cache'); $oAuthorsView = $aData['view']; $aDetails = $aData['details']; } else { wfDebugLog('BsMemcached', __CLASS__ . ': Fetching AuthorsView and Details from DB'); //HINT: Maybe we want to use MW interface Article::getContributors() to have better caching //HINT2: Check if available in MW 1.17+ // SW: There is still no caching in WikiPage::getContributors()! 17.07.2014 $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select(array('revision'), array('rev_user_text', 'MAX(rev_timestamp) AS ts'), array('rev_page' => $iArticleId), __METHOD__, array('GROUP BY' => 'rev_user_text', 'ORDER BY' => 'ts DESC')); if ($res->numRows() == 0) { return true; } $oAuthorsView = new ViewAuthors(); if ($sPrintable == 'yes') { $oAuthorsView->setOption('print', true); } $aUserNames = array(); foreach ($res as $row) { $aUserNames[] = $row->rev_user_text; } $iCount = count($aUserNames); $aDetails['count'] = $iCount; $sOriginatorUserName = $oTitle->getFirstRevision()->getUserText(); $sOriginatorUserName = $this->checkOriginatorForBlacklist($sOriginatorUserName, $oTitle->getFirstRevision(), $aBlacklist); if ($iCount > 1) { array_unshift($aUserNames, $sOriginatorUserName); $iCount++; } $bAddMore = false; if ($iCount > $iLimit) { $bAddMore = true; } $i = 0; $iItems = 0; $aDetails['username'] = ''; while ($i < $iCount) { if ($iItems > $iLimit) { break; } $sUserName = $aUserNames[$i]; if (User::isIP($sUserName)) { unset($aUserNames[$i]); $i++; continue; } $oAuthorUser = User::newFromName($sUserName); if (!is_object($oAuthorUser) || in_array($oAuthorUser->getName(), $aBlacklist)) { unset($aUserNames[$i]); $i++; continue; } $aDetails['username'] = $oAuthorUser->getName(); $oUserMiniProfileView = BsCore::getInstance()->getUserMiniProfile($oAuthorUser, $aParams); if ($sPrintable == 'yes') { $oUserMiniProfileView->setOption('print', true); } $iItems++; $i++; $oAuthorsView->addItem($oUserMiniProfileView); } if ($bAddMore === true) { $oMoreAuthorsView = BsCore::getInstance()->getUserMiniProfile(new User(), $aParams); $oMoreAuthorsView->setOption('userdisplayname', wfMessage('bs-authors-show-all-authors')->plain()); $oMoreAuthorsView->setOption('userimagesrc', $this->getImagePath(true) . '/' . $sMoreImage); $oMoreAuthorsView->setOption('linktargethref', $oTitle->getLocalURL(array('action' => 'history'))); $oMoreAuthorsView->setOption('classes', array('bs-authors-more-icon')); if ($sPrintable == 'yes') { $oMoreAuthorsView->setOption('print', true); } $oAuthorsView->addItem($oMoreAuthorsView); } $dbr->freeResult($res); BsCacheHelper::set($sKey, array('view' => $oAuthorsView, 'details' => $aDetails)); } return $oAuthorsView; }
/** * * @param array $aResponsibleEditorIds * @param User $oUser * @param array $aTitles * @param string $sAction */ public static function notifyResponsibleEditors($aResponsibleEditorIds, $oUser, $aTitles, $sAction) { if (empty($aResponsibleEditorIds)) { return true; } foreach ($aResponsibleEditorIds as $iUserId) { $oREUser = User::newFromId($iUserId); if ($iUserId == $oUser->getId()) { continue; } if (BsConfig::getVarForUser("MW::ResponsibleEditors::E" . ucfirst($sAction), $oREUser) === false) { continue; } $sUserRealName = BsCore::getInstance()->getUserDisplayName($oUser); $sUsername = $oUser->getName(); $sArticleName = $aTitles[0]->getText(); $sArticleLink = $aTitles[0]->getFullURL(); $sLanguageCode = $oREUser->getOption('language'); switch ($sAction) { case 'change': $sSubject = wfMessage('bs-responsibleeditors-mail-subject-re-article-changed', $sArticleName, $sUsername, $sUserRealName)->inLanguage($sLanguageCode)->text(); $sMessage = wfMessage('bs-responsibleeditors-mail-text-re-article-changed', $sArticleName, $sUsername, $sUserRealName, $sArticleLink)->inLanguage($sLanguageCode)->text(); break; case 'delete': $sSubject = wfMessage('bs-responsibleeditors-mail-subject-re-article-deleted', $sArticleName, $sUsername, $sUserRealName)->inLanguage($sLanguageCode)->text(); $sMessage = wfMessage('bs-responsibleeditors-mail-text-re-article-deleted', $sArticleName, $sUsername, $sUserRealName, $sArticleLink)->inLanguage($sLanguageCode)->text(); break; case 'move': $sSubject = wfMessage('bs-responsibleeditors-mail-subject-re-article-moved', $sArticleName, $sUsername, $sUserRealName)->inLanguage($sLanguageCode)->text(); $sMessage = wfMessage('bs-responsibleeditors-mail-text-re-article-moved', $sArticleName, $aTitles[1]->getPrefixedText(), $sUsername, $sUserRealName, $sArticleLink)->inLanguage($sLanguageCode)->text(); break; default: wfDebugLog('BS::ResponsibleEditors::notifyResponsibleEditors', 'Action "' . $sAction . '" is unknown. No mails sent.'); return; } BsMailer::getInstance('MW')->send($oREUser, $sSubject, $sMessage); } }
/** * Returns a JSON encoded list of users. Called by review handler * @return bool Just some return value. Looks nice. */ public static function getUsers() { if (BsCore::checkAccessAdmission('read') === false) { return true; } $aJsonOut = array(); $aJsonOut['users'] = array(); $dbw = wfGetDB(DB_MASTER); $res = $dbw->select('user', 'user_id, user_name', '', '', array('ORDER BY' => 'user_name')); while ($row = $dbw->fetchRow($res)) { $aUser = array(); $oUser = User::newFromName($row['user_name']); $aUser['username'] = $oUser->getName(); $aUser['userid'] = $row['user_id']; $aUser['displayname'] = BsCore::getInstance()->getUserDisplayName($oUser); #$oReviewFormView->addAssessor( $oUser->getName(), $this->mCore->getUserDisplayName( $oUser ) ); //} $aJsonOut['users'][] = $aUser; } return json_encode($aJsonOut); }
/** * Searches the DOM for <img>-Tags and <a> Tags with class 'internal', * resolves the local filesystem path and adds it to $aFiles array. * @param DOMDocument $oHtml The markup to be searched. * @return boolean Well, always true. */ protected function findFiles(&$oHtml) { //Find all images $oImageElements = $oHtml->getElementsByTagName('img'); foreach ($oImageElements as $oImageElement) { $sSrcUrl = urldecode($oImageElement->getAttribute('src')); $sSrcFilename = basename($sSrcUrl); $bIsThumb = UploadBase::isThumbName($sSrcFilename); $sTmpFilename = $sSrcFilename; if ($bIsThumb) { //HINT: Thumbname-to-filename-conversion taken from includes/Upload/UploadBase.php //Check for filenames like 50px- or 180px-, these are mostly thumbnails $sTmpFilename = substr($sTmpFilename, strpos($sTmpFilename, '-') + 1); } $oFileTitle = Title::newFromText($sTmpFilename, NS_FILE); $oImage = RepoGroup::singleton()->findFile($oFileTitle); if ($oImage instanceof File && $oImage->exists()) { $oFileRepoLocalRef = $oImage->getRepo()->getLocalReference($oImage->getPath()); if (!is_null($oFileRepoLocalRef)) { $sAbsoluteFileSystemPath = $oFileRepoLocalRef->getPath(); } $sSrcFilename = $oImage->getName(); } else { $sAbsoluteFileSystemPath = $this->getFileSystemPath($sSrcUrl); } // TODO RBV (05.04.12 11:48): Check if urlencode has side effects $oImageElement->setAttribute('src', 'images/' . urlencode($sSrcFilename)); $sFileName = $sSrcFilename; wfRunHooks('BSUEModulePDFWebserviceFindFiles', array($this, $oImageElement, $sAbsoluteFileSystemPath, $sFileName, 'IMAGE')); $this->aFiles['IMAGE'][$sFileName] = $sAbsoluteFileSystemPath; } $oDOMXPath = new DOMXPath($oHtml); /* * This is now in template //Find all CSS files $oLinkElements = $oHtml->getElementsByTagName( 'link' ); // TODO RBV (02.02.11 16:48): Limit to rel="stylesheet" and type="text/css" foreach( $oLinkElements as $oLinkElement ) { $sHrefUrl = $oLinkElement->getAttribute( 'href' ); $sHrefFilename = basename( $sHrefUrl ); $sAbsoluteFileSystemPath = $this->getFileSystemPath( $sHrefUrl ); $this->aFiles[ $sAbsoluteFileSystemPath ] = array( $sHrefFilename, 'STYLESHEET' ); $oLinkElement->setAttribute( 'href', 'stylesheets/'.$sHrefFilename ); } */ //Find all files for attaching and merging... if ($this->aParams['pdf-merging'] == '1' || $this->aParams['attachments'] == '1') { $sUploadPath = BsCore::getInstance()->getAdapter()->get('UploadPath'); // TODO RBV (08.02.11 15:15): Necessary to exclude images? $oFileAnchorElements = $oDOMXPath->query("//a[contains(@class,'internal') and not(contains(@class, 'image'))]"); foreach ($oFileAnchorElements as $oFileAnchorElement) { $sHref = urldecode($oFileAnchorElement->getAttribute('href')); $vUploadPathIndex = strpos($sHref, $sUploadPath); if ($vUploadPathIndex !== false) { $sRelativeHref = substr($sHref, $vUploadPathIndex); $sHrefFilename = basename($sRelativeHref); $sAbsoluteFileSystemPath = $this->getFileSystemPath($sRelativeHref); if ($this->aParams['attachments'] == '1') { wfRunHooks('BSUEModulePDFWebserviceFindFiles', array($this, $oFileAnchorElement, $sAbsoluteFileSystemPath, $sHrefFilename, 'ATTACHMENT')); $this->aFiles['ATTACHMENT'][$sHrefFilename] = $sAbsoluteFileSystemPath; } } } } return true; }
/** * Delivers a rendered list of shouts for the current page to be displayed in the shoutbox. * This function is called remotely via AJAX-Handler. * @param string $sOutput contains the rendered list * @return bool allow other hooked methods to be executed. Always true */ public static function getShouts($iArticleId, $iLimit) { if (BsCore::checkAccessAdmission('readshoutbox') === false) { return ""; } // do not allow negative page ids and pages that have 0 as id (e.g. special pages) if ($iArticleId <= 0) { return true; } if ($iLimit <= 0) { $iLimit = BsConfig::get('MW::ShoutBox::NumberOfShouts'); } $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'ShoutBox', $iArticleId, $iLimit); $aData = BsCacheHelper::get($sKey); $aData = false; if ($aData !== false) { wfDebugLog('BsMemcached', __CLASS__ . ': Fetching shouts from cache'); $sOutput = $aData; } else { wfDebugLog('BsMemcached', __CLASS__ . ': Fetching shouts from DB'); $sOutput = ''; //return false on hook handler to break here $aTables = array('bs_shoutbox'); $aFields = array('*'); $aConditions = array('sb_page_id' => $iArticleId, 'sb_archived' => '0', 'sb_parent_id' => '0', 'sb_title' => ''); $aOptions = array('ORDER BY' => 'sb_timestamp DESC', 'LIMIT' => $iLimit + 1); if (!wfRunHooks('BSShoutBoxGetShoutsBeforeQuery', array(&$sOutput, $iArticleId, &$iLimit, &$aTables, &$aFields, &$aConditions, &$aOptions))) { return $sOutput; } $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select($aTables, $aFields, $aConditions, __METHOD__, $aOptions); $oShoutBoxMessageListView = new ViewShoutBoxMessageList(); if ($dbr->numRows($res) > $iLimit) { $oShoutBoxMessageListView->setMoreLimit($iLimit + BsConfig::get('MW::ShoutBox::NumberOfShouts')); } $bShowAge = BsConfig::get('MW::ShoutBox::ShowAge'); $bShowUser = BsConfig::get('MW::ShoutBox::ShowUser'); $iCount = 0; while ($row = $dbr->fetchRow($res)) { $oUser = User::newFromId($row['sb_user_id']); $oProfile = BsCore::getInstance()->getUserMiniProfile($oUser); $sMessage = preg_replace_callback("#@(\\S*)#", "self::replaceUsernameInMessage", $row['sb_message']); $oShoutBoxMessageView = new ViewShoutBoxMessage(); if ($bShowAge) { $oShoutBoxMessageView->setDate(BsFormatConverter::mwTimestampToAgeString($row['sb_timestamp'], true)); } if ($bShowUser) { $oShoutBoxMessageView->setUsername($row['sb_user_name']); } $oShoutBoxMessageView->setUser($oUser); $oShoutBoxMessageView->setMiniProfile($oProfile); $oShoutBoxMessageView->setMessage($sMessage); $oShoutBoxMessageView->setShoutID($row['sb_id']); $oShoutBoxMessageListView->addItem($oShoutBoxMessageView); // Since we have one more shout than iLimit, we need to count :) $iCount++; if ($iCount >= $iLimit) { break; } } $sOutput .= $oShoutBoxMessageListView->execute(); $iTotelShouts = self::getTotalShouts($iArticleId); $sOutput .= "<div id='bs-sb-count-all' style='display:none'>" . $iTotelShouts . "</div>"; //expire after 5 minutes in order to keep time tracking somewhat up-to-date BsCacheHelper::set($sKey, $sOutput, 60 * 5); $dbr->freeResult($res); } return $sOutput; }
/** * Get the Users for specialpage, called via ajax * @param string $sPage page title * @return bool Always true */ public static function getUsers($sPage) { $oTitle = Title::newFromText($sPage); if (!$oTitle->exists()) { return json_encode(array()); } $iArticleID = $oTitle->getArticleID(); $oStoreParams = BsExtJSStoreParams::newFromRequest(); $iLimit = $oStoreParams->getLimit(); $iStart = $oStoreParams->getStart(); $sSort = $oStoreParams->getSort('MAX(readers_ts)'); $sDirection = $oStoreParams->getDirection(); if ($sSort == 'user_name') { $sSort = 'readers_user_name'; } elseif ($sSort == 'user_ts') { $sSort = 'readers_ts'; } elseif ($sSort == 'user_readers') { $sSort = 'readers_user_name'; } $oDbr = wfGetDB(DB_SLAVE); $res = $oDbr->select(array('bs_readers'), array('readers_user_id', 'MAX(readers_ts) as readers_ts'), array('readers_page_id' => $iArticleID), __METHOD__, array('GROUP BY' => 'readers_user_id', 'ORDER BY' => $sSort . ' ' . $sDirection, 'LIMIT' => $iLimit, 'OFFSET' => $iStart)); $aUsers = array(); if ($oDbr->numRows($res) > 0) { $aParams = array(); $oLanguage = RequestContext::getMain()->getLanguage(); foreach ($res as $row) { $oUser = User::newFromId((int) $row->readers_user_id); $oTitle = Title::makeTitle(NS_USER, $oUser->getName()); $oUserMiniProfile = BsCore::getInstance()->getUserMiniProfile($oUser, $aParams); $sImage = $oUserMiniProfile->getUserImageSrc(); if (BsExtensionManager::isContextActive('MW::SecureFileStore::Active')) { $sImage = SecureFileStore::secureStuff($sImage, true); } $aTmpUser = array(); $aTmpUser['user_image'] = $sImage; $aTmpUser['user_name'] = $oUser->getName(); $aTmpUser['user_page'] = $oTitle->getLocalURL(); $aTmpUser['user_readers'] = SpecialPage::getTitleFor('Readers', $oTitle->getPrefixedText())->getLocalURL(); $aTmpUser['user_ts'] = $row->readers_ts; $aTmpUser['user_date'] = $oLanguage->timeanddate($row->readers_ts); $aUsers['users'][] = $aTmpUser; } } $rowCount = $oDbr->select('bs_readers', 'readers_user_id', array('readers_page_id' => $iArticleID), __METHOD__, array('GROUP BY' => 'readers_user_id')); $aUsers['totalCount'] = $oDbr->numRows($rowCount); return json_encode($aUsers); }
/** * * @global User $wgUser * @param array $aNewEditorIds * @param array $aRemovedEditorIds * @param array $aUntouchedEditorIds * @param int $iArticleId * @return void */ public static function notifyAffectedUsers($aNewEditorIds, $aRemovedEditorIds, $aUntouchedEditorIds, $iArticleId) { global $wgUser; if (BsConfig::get('MW::ResponsibleEditors::EMailNotificationOnResponsibilityChange') != true) { return; } $oCore = BsCore::getInstance(); $oArticleTitle = Title::newFromID($iArticleId); $sArticleName = $oArticleTitle->getPrefixedText(); $sArticleLink = $oArticleTitle->getFullURL(); $sChangingUserName = $oCore->getUserDisplayName($wgUser); $sUsername = $wgUser->getName(); //Notify new editors $aNewEditors = array(); foreach ($aNewEditorIds as $iUserId) { if ($wgUser->getId() == $iUserId) { continue; } //Skip notification if user changes responsibility himself $oUser = User::newFromId($iUserId); $aNewEditors[] = $oUser; } $sSubject = wfMessage('bs-responsibleeditors-mail-subject-new-editor', $sArticleName)->text(); $sMessage = wfMessage('bs-responsibleeditors-mail-text-new-editor', $sUsername, $sChangingUserName, $sArticleName, $sArticleLink)->text(); BsMailer::getInstance('MW')->send($aNewEditors, $sSubject, $sMessage); //Notify untouched editors $aUntouchedEditors = array(); foreach ($aUntouchedEditorIds as $iUserId) { if ($wgUser->getId() == $iUserId) { continue; } //Skip notification if user changes responsibility himself $aUntouchedEditors[] = User::newFromId($iUserId); } //Notify removed editors $aRemovedEditors = array(); if (empty($aRemovedEditorIds)) { return; } foreach ($aRemovedEditorIds as $iUserId) { if ($wgUser->getId() == $iUserId) { continue; } //Skip notification if user changes responsibility himself $oUser = User::newFromId($iUserId); $aRemovedEditors[] = $oUser; } $aCurrentRespEdNames = array(); $aCurrentRespEdIds = $aUntouchedEditorIds + $aNewEditorIds; foreach ($aCurrentRespEdIds as $oCurrentRespEdUserId) { $aCurrentRespEdNames[] = $oCore->getUserDisplayName(User::newFromId($oCurrentRespEdUserId)); } $sSubject = wfMessage('bs-responsibleeditors-mail-subject-former-editor', $sArticleName)->plain(); $sMessage = wfMessage('bs-responsibleeditors-mail-text-former-editor', $sUsername, $sChangingUserName, $sArticleName, implode(', ', $aCurrentRespEdNames), count($aCurrentRespEdNames), $sArticleLink)->text(); BsMailer::getInstance('MW')->send($aRemovedEditors, $sSubject, $sMessage); }