/**
  * 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 .= '&nbsp;';
     } 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);
 }