public function testIteratorImplementation() { $this->assertInstanceOf('IteratorAggregate', $this->instance, 'be sure that PHP handle getIterator'); $message = $this->getMock('Qu\\Message\\MessageInterface'); $this->instance->addMessage($message)->addMessage($message); $iterator = $this->instance->getIterator(); $this->assertSame([$message, $message], $iterator->getArrayCopy(), 'iterator contains messages'); }
protected function doAuthors(MessageCollection $collection) { $output = ''; $authors = $collection->getAuthors(); $authors = $this->filterAuthors($authors, $collection->code); foreach ($authors as $author) { $output .= "# Author: {$author}\n"; } return $output; }
/** * @dataProvider provideTestFiles */ public function testParsing($file) { $filename = basename($file); list($pagename, ) = explode('.', $filename, 2); $title = Title::newFromText($pagename); $translatablePage = TranslatablePage::newFromText($title, file_get_contents($file)); $pattern = $file; if ($filename === 'FailNotAtomic.ptfile') { $this->markTestSkipped('Extended validation not yet implemented'); } $failureExpected = strpos($pagename, 'Fail') === 0; if ($failureExpected) { $this->setExpectedException('TPException'); } $parse = $translatablePage->getParse(); $this->assertInstanceOf('TPParse', $parse); if (file_exists("{$pattern}.ptsource")) { $source = $parse->getSourcePageText(); $this->assertEquals($source, file_get_contents("{$pattern}.ptsource")); } if (file_exists("{$pattern}.pttarget")) { $target = $parse->getTranslationPageText(MessageCollection::newEmpty('foo')); $this->assertEquals($target, file_get_contents("{$pattern}.pttarget")); } // Custom tests written in php if (file_exists("{$pattern}.pttest")) { require "{$pattern}.pttest"; } }
/** * Takes a slice of messages according to limit and offset given * in option at initialisation time. Calls the callback to provide * information how much messages there is. */ protected function doPaging() { $total = count($this->collection); $offsets = $this->collection->slice($this->options['offset'], $this->options['limit']); $left = count($this->collection); $this->offsets = array('backwardsOffset' => $offsets[0], 'forwardsOffset' => $offsets[1], 'start' => $offsets[2], 'count' => $left, 'total' => $total); }
protected function writeReal(MessageCollection $collection) { $output = ''; $mangler = $this->group->getMangler(); /** * @var $m ThinMessage */ foreach ($collection as $key => $m) { $value = $m->translation(); if ($value === null) { continue; } $comment = ''; if ($m->hasTag('fuzzy')) { $value = str_replace(TRANSLATE_FUZZY, '', $value); $comment = "; Fuzzy\n"; } $key = $mangler->unmangle($key); $output .= "{$comment}{$key} = {$value}\n"; } // Do not create empty files if ($output === '') { return ''; } global $wgSitename; // Accumulator $header = "; Exported from {$wgSitename}\n"; $authors = $collection->getAuthors(); $authors = $this->filterAuthors($authors, $collection->getLanguage()); foreach ($authors as $author) { $header .= "; Author: {$author}\n"; } $header .= '[' . $collection->getLanguage() . "]\n"; return $header . $output; }
protected function doLinkBatch() { $batch = new LinkBatch(); $batch->setCaller(__METHOD__); foreach ($this->collection->getTitles() as $title) { $batch->addObj($title); } $batch->execute(); }
protected function writeReal(MessageCollection $collection) { $template = <<<XML <?xml version="1.0" encoding="utf-8"?> <resources></resources> XML; $writer = new SimpleXMLElement($template); $mangler = $this->group->getMangler(); $collection->filter('hastranslation', false); if (count($collection) === 0) { return ''; } /** * @var $m TMessage */ foreach ($collection as $key => $m) { $key = $mangler->unmangle($key); $value = $m->translation(); $value = str_replace(TRANSLATE_FUZZY, '', $value); // Handle plurals if (strpos($value, '{{PLURAL') === false) { $element = $writer->addChild('string', $this->formatElementContents($value)); } else { $element = $writer->addChild('plurals'); $forms = $this->unflattenPlural($value); foreach ($forms as $quantity => $content) { $item = $element->addChild('item', $this->formatElementContents($content)); $item->addAttribute('quantity', $quantity); } } $element->addAttribute('name', $key); // This is non-standard if ($m->hasTag('fuzzy')) { $element->addAttribute('fuzzy', 'true'); } } // Make the output pretty with DOMDocument $dom = new DOMDocument('1.0'); $dom->formatOutput = true; $dom->loadXML($writer->asXML()); return $dom->saveXML(); }
public function execute() { $dir = dirname( __FILE__ ); $testDirectory = "$dir/../tests/pagetranslation"; $testFiles = glob( "$testDirectory/*.ptfile" ); foreach ( $testFiles as $file ) { $filename = basename( $file ); list( $pagename, ) = explode( '.', $filename, 2 ); $title = Title::newFromText( $pagename ); $translatablePage = TranslatablePage::newFromText( $title, file_get_contents( $file ) ); $pattern = realpath( "$testDirectory" ) . "/$pagename"; $failureExpected = strpos( $pagename, 'Fail' ) === 0; try { $parse = $translatablePage->getParse(); if ( $failureExpected ) { $target = $parse->getTranslationPageText( MessageCollection::newEmpty( "foo" ) ); $this->output( "Testfile $filename should have failed... see $pattern.pttarget.fail\n" ); file_put_contents( "$pattern.pttarget.fail", $target ); } } catch ( TPException $e ) { if ( !$failureExpected ) { $this->output( "Testfile $filename failed to parse... see $pattern.ptfile.fail\n" ); file_put_contents( "$pattern.ptfile.fail", $e->getMessage() ); } continue; } if ( file_exists( "$pattern.ptsource" ) ) { $source = $parse->getSourcePageText(); if ( $source !== file_get_contents( "$pattern.ptsource" ) ) { $this->output( "Testfile $filename failed with source page output... writing $pattern.ptsource.fail\n" ); file_put_contents( "$pattern.ptsource.fail", $source ); } } if ( file_exists( "$pattern.pttarget" ) ) { $target = $parse->getTranslationPageText( MessageCollection::newEmpty( "foo" ) ); if ( $target !== file_get_contents( "$pattern.pttarget" ) ) { $this->output( "Testfile $filename failed with target page output... writing $pattern.pttarget.fail\n" ); file_put_contents( "$pattern.pttarget.fail", $target ); } } // Custom tests written in php if ( file_exists( "$pattern.pttest" ) ) { require( "$pattern.pttest" ); } } }
/** * @param MessageCollection $collection * @return string */ protected function writeReal(MessageCollection $collection) { $messages = array(); $template = $this->read($collection->getLanguage()); if (isset($template['METADATA'])) { $messages['@metadata'] = $template['METADATA']; } $authors = $collection->getAuthors(); $authors = $this->filterAuthors($authors, $collection->code); if (isset($template['AUTHORS'])) { $authors = array_unique(array_merge($template['AUTHORS'], $authors)); } if ($authors !== array()) { $messages['@metadata']['authors'] = array_values($authors); } $mangler = $this->group->getMangler(); /** * @var $m ThinMessage */ foreach ($collection as $key => $m) { $value = $m->translation(); if ($value === null) { continue; } if ($m->hasTag('fuzzy')) { $value = str_replace(TRANSLATE_FUZZY, '', $value); } $key = $mangler->unmangle($key); $messages[$key] = $value; } // Do not create empty files if (!count($messages)) { return ''; } return FormatJson::encode($messages, "\t", FormatJson::ALL_OK) . "\n"; }
protected function extractMessages($resultset, $offset, $limit) { $messages = $documents = $ret = array(); $language = $this->params['language']; foreach ($resultset->getResults() as $document) { $data = $document->getData(); if (!$this->server->isLocalSuggestion($data)) { continue; } $title = Title::newFromText($data['localid']); if (!$title) { continue; } $handle = new MessageHandle($title); if (!$handle->isValid()) { continue; } $key = $title->getNamespace() . ':' . $title->getDBKey(); $messages[$key] = $data['content']; } $definitions = new MessageDefinitions($messages); $collection = MessageCollection::newFromDefinitions($definitions, $language); $filter = $this->params['filter']; if ($filter === 'untranslated') { $collection->filter('hastranslation', true); } elseif (in_array($filter, $this->getAvailableFilters())) { $collection->filter($filter, false); } $total = count($collection); $offset = $collection->slice($offset, $limit); $left = count($collection); $offsets = array('start' => $offset[2], 'left' => $left, 'total' => $total); if ($filter === 'translated' || $filter === 'fuzzy') { $collection->loadTranslations(); } foreach ($collection->keys() as $mkey => $title) { $documents[$mkey]['content'] = $messages[$mkey]; if ($filter === 'translated' || $filter === 'fuzzy') { $documents[$mkey]['content'] = $collection[$mkey]->translation(); } $handle = new MessageHandle($title); $documents[$mkey]['localid'] = $handle->getTitleForBase()->getPrefixedText(); $documents[$mkey]['language'] = $language; $ret[] = $documents[$mkey]; } return array($ret, $offsets); }
/** * @param MessageCollection $collection * @return string */ protected function writeReal(MessageCollection $collection) { $messages = array(); $mangler = $this->group->getMangler(); /** @var ThinMessage $m */ foreach ($collection as $key => $m) { $value = $m->translation(); if ($value === null) { continue; } if ($m->hasTag('fuzzy')) { $value = str_replace(TRANSLATE_FUZZY, '', $value); } $key = $mangler->unmangle($key); $messages[$key] = $value; } // Do not create empty files if (!count($messages)) { return ''; } $header = $this->header($collection->code, $collection->getAuthors()); return $header . FormatJson::encode($messages, "\t", FormatJson::UTF8_OK) . ");\n"; }
public function webExport( MessageCollection $collection ) { $code = $collection->code; // shorthand // Open temporary stream $handle = fopen( 'php://temp', 'wt' ); $this->addAuthors( $collection->getAuthors(), $code ); $this->exportLanguage( $handle, $collection ); // Fetch data rewind( $handle ); $data = stream_get_contents( $handle ); fclose( $handle ); return $data; }
/** * @param $collection MessageCollection * @return string */ protected function doAuthors( MessageCollection $collection ) { $output = ''; // Read authors. $fr = fopen( $this->group->getSourceFilePath( $collection->code ), 'r' ); $authors = array(); while ( !feof( $fr ) ) { $line = fgets( $fr ); if ( strpos( $line, "\t# Author:" ) === 0 ) { $authors[] = trim( substr( $line, strlen( "\t# Author: " ) ) ); } elseif ( $line === "\t'{$collection->code}': {\n" ) { break; } else { $authors = array(); } } $authors2 = $collection->getAuthors(); $authors2 = $this->filterAuthors( $authors2, $collection->code ); $authors = array_unique( array_merge( $authors, $authors2 ) ); foreach ( $authors as $author ) { $output .= "\t# Author: $author\n"; } return $output; }
/** * This tries to pick up external authors in the source files so that they * are not lost if those authors are not among those who have translated in * the wiki. * * @todo Get rid of this * @param string $filename * @param MessageCollection $collection */ protected function tryReadSource($filename, MessageCollection $collection) { if (get_class($this->group->getFFS()) !== get_class($this)) { return; } $sourceText = $this->tryReadFile($filename); // No need to do anything in SimpleFFS if it's false, // it only reads author data from it. if ($sourceText !== false) { $sourceData = $this->readFromVariable($sourceText); if (isset($sourceData['AUTHORS'])) { $collection->addCollectionAuthors($sourceData['AUTHORS']); } } }
protected function setTags(MessageCollection $collection) { foreach ($this->getTags() as $type => $tags) { $collection->setTags($type, $tags); } }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param \MailSo\Cache\CacheClient|null $oCacher = null * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() * @param bool $bUseESearchOrESortRequest = false * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array(), $bUseESearchOrESortRequest = false) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $this->oImapClient->FolderExamine($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $aLastCollapsedThreadUids = array(); $aThreads = array(); $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $iMessageCount = $iMessageRealCount; $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); $bSearch = false; $bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger && \MailSo\Config::$MessageListCountLimitTrigger < $iMessageRealCount; if ($bMessageListOptimization) { $bUseSortIfSupported = false; $bUseThreadSortIfSupported = false; $bUseESearchOrESortRequest = false; } if (0 < $iMessageRealCount) { $bIndexAsUid = false; $aIndexOrUids = array(); if (0 < \strlen($sSearch)) { $aIndexOrUids = $this->getSearchUidsResult($sSearch, $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $bIndexAsUid = true; } else { if ($bUseThreadSortIfSupported && 1 < $iMessageCount) { $aIndexOrUids = $this->getSearchUidsResult('', $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $aIndexOrUids, $oCacher, \MailSo\Config::$LargeThreadLimit); $aExpandedThreadsUids = \is_array($aExpandedThreadsUids) ? $aExpandedThreadsUids : array(); $bWatchExpanded = 0 < \count($aExpandedThreadsUids); $aNewIndexOrUids = array(); foreach ($aIndexOrUids as $iUid) { if (isset($aThreads[$iUid])) { $aNewIndexOrUids[] = $iUid; if (\is_array($aThreads[$iUid])) { if ($bWatchExpanded && \in_array($iUid, $aExpandedThreadsUids)) { $aSubArray = $aThreads[$iUid]; foreach ($aSubArray as $iSubRootUid) { $aNewIndexOrUids[] = $iSubRootUid; } } else { $aLastCollapsedThreadUids[] = $iUid; } } } } $aIndexOrUids = $aNewIndexOrUids; unset($aNewIndexOrUids); $iMessageCount = \count($aIndexOrUids); $bIndexAsUid = true; } else { $aIndexOrUids = array(1); $bIndexAsUid = false; if (1 < $iMessageCount) { if ($bMessageListOptimization || 0 === \MailSo\Config::$MessageListDateFilter) { $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); } else { $aIndexOrUids = $this->getSearchUidsResult('', $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $bIndexAsUid = true; } } } } if (\is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) ? $iMessageCount : \count($aIndexOrUids); if (0 < \count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); } } } $aLastCollapsedThreadUidsForPage = array(); if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) { $iUid = $oMessage->Uid(); if (\in_array($iUid, $aLastCollapsedThreadUids)) { $aLastCollapsedThreadUidsForPage[] = $iUid; } if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); $oMessage->SetThreadsLen(\count($aThreads[$iUid])); } else { if (!isset($aThreads[$iUid])) { foreach ($aThreads as $iKeyUid => $mSubItem) { if (\is_array($mSubItem) && \in_array($iUid, $mSubItem)) { $oMessage->SetParentThread($iKeyUid); $oMessage->SetThreadsLen(\count($mSubItem)); } } } } }); $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; } return $oMessageCollection; }
public function initCollection($code) { $messages = $this->loadMessagesFromCache($this->getGroups()); $namespace = $this->getNamespace(); $definitions = new MessageDefinitions($messages, $namespace); $collection = MessageCollection::newFromDefinitions($definitions, $code); $this->setTags($collection); return $collection; }
public function testAddMessage() { $this->messages->add(new Message('One')); $this->assertEquals('One', $this->messages->get(0)); }
function fill(MessageCollection $messages) { $cache = $this->load($messages->code); foreach ($messages->getMessageKeys() as $key) { if (isset($cache[$key])) { if (is_array($cache[$key])) { $messages[$key]->setInfile(implode(',', $cache[$key])); } else { $messages[$key]->setInfile($cache[$key]); } } } }
public function initCollection( $code ) { $messages = array(); foreach ( $this->getGroups() as $group ) { $cache = new MessageGroupCache( $group ); if ( $cache->exists() ) { foreach ( $cache->getKeys() as $key ) { $messages[$key] = $cache->get( $key ); } } else { // BC for MessageGroupOld $messages += $group->load( $this->getSourceLanguage() ); } } $namespace = $this->getNamespace(); $definitions = new MessageDefinitions( $messages, $namespace ); $collection = MessageCollection::newFromDefinitions( $definitions, $code ); $this->setTags( $collection ); return $collection; }
/** * @param MessageCollection $collection * @return string */ protected function writeReal(MessageCollection $collection) { $mangler = $this->group->getMangler(); $code = $collection->getLanguage(); $block = $this->generateMessageBlock($collection, $mangler); if ($block === false) { return ''; } // Ugly code, relies on side effects // Avoid parsing stuff with fake language code // Premature optimization $this->read('mul'); $filename = $this->group->getSourceFilePath($code); $cache =& self::$cache[$filename]; // Generating authors if (isset($cache['sections'][$code])) { // More premature optimization $fromFile = self::parseAuthorsFromString($cache['sections'][$code]); $collection->addCollectionAuthors($fromFile); } $authors = $collection->getAuthors(); $authors = $this->filterAuthors($authors, $code); $authorList = ''; foreach ($authors as $author) { $authorList .= "\n * @author {$author}"; } // And putting all together $name = TranslateUtils::getLanguageName($code); $native = TranslateUtils::getLanguageName($code, $code); $section = <<<PHP /** {$name} ({$native}){$authorList} */ \$messages['{$code}'] = array({$block}); PHP; // Store the written part, so that when next language is called, // the new version will be used (instead of the old parsed version $cache['sections'][$code] = $section; // Make a copy we can alter $sections = $cache['sections']; $priority = array(); global $wgTranslateDocumentationLanguageCode; $codes = array(0, $this->group->getSourceLanguage(), $wgTranslateDocumentationLanguageCode); foreach ($codes as $pcode) { if (isset($sections[$pcode])) { $priority[] = $sections[$pcode]; unset($sections[$pcode]); } } ksort($sections); return implode("\n\n", $priority) . "\n\n" . implode("\n\n", $sections) . "\n"; }
/** * @param $collection MessageCollection * @return string */ public function writeReal(MessageCollection $collection) { $header = $this->header($collection->code, $collection->getAuthors()); $mangler = $this->group->getMangler(); /** * Get and write messages. */ $body = ''; /** * @var TMessage $message */ foreach ($collection as $message) { if (strlen($message->translation()) === 0) { continue; } $key = $mangler->unmangle($message->key()); $key = $this->transformKey(self::escapeJsString($key)); $translation = self::escapeJsString($message->translation()); $body .= "\t{$key}: \"{$translation}\",\n"; } if (strlen($body) === 0) { return false; } /** * Strip last comma, re-add trailing newlines. */ $body = substr($body, 0, -2); $body .= "\n"; return $header . $body . $this->footer(); }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param \MailSo\Cache\CacheClient|null $oCacher = null * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param bool $bUseESearchOrESortRequest = false * @param string $sThreadUid = '' * @param string $sFilter = '' * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '', $sFilter = '') { $sFilter = \trim($sFilter); $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $bUseFilter = '' !== $sFilter; $this->oImapClient->FolderSelect($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $oMessageCollection->ThreadUid = $sThreadUid; $oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter; $aUids = array(); $mAllSortedUids = null; $mAllThreads = null; $iThreadUid = empty($sThreadUid) ? 0 : (int) $sThreadUid; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $sHighestModSeq = ''; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!empty($sThreadUid) && !$bUseThreadSortIfSupported) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); if ($bUseFilter) { $iMessageUnseenCount = 0; } $oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); $oMessageCollection->UidNext = $sUidNext; if (empty($sThreadUid) && 0 < \strlen($sPrevUidNext) && 'INBOX' === $sFolderName) { $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); } $bSearch = false; $bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger && \MailSo\Config::$MessageListCountLimitTrigger < $iMessageRealCount; if ($bMessageListOptimization) { $bUseSortIfSupported = false; $bUseThreadSortIfSupported = false; } if (0 < $iMessageRealCount && !$bMessageListOptimization) { $mAllSortedUids = $this->GetUids($oCacher, '', $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported); $mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $mAllSortedUids, $oCacher) : null; if ($bUseThreadSortIfSupported && 0 < $iThreadUid && \is_array($mAllThreads)) { $aUids = array(); $iResultRootUid = 0; if (isset($mAllThreads[$iThreadUid])) { $iResultRootUid = $iThreadUid; if (\is_array($mAllThreads[$iThreadUid])) { $aUids = $mAllThreads[$iThreadUid]; } } else { foreach ($mAllThreads as $iRootUid => $mSubUids) { if (\is_array($mSubUids) && \in_array($iThreadUid, $mSubUids)) { $iResultRootUid = $iRootUid; $aUids = $mSubUids; continue; } } } if (0 < $iResultRootUid && \in_array($iResultRootUid, $mAllSortedUids)) { \array_unshift($aUids, $iResultRootUid); } } else { if ($bUseThreadSortIfSupported && \is_array($mAllThreads)) { $aUids = \array_keys($mAllThreads); } else { $bUseThreadSortIfSupported = false; $aUids = $mAllSortedUids; } } if (0 < \strlen($sSearch) && \is_array($aUids)) { $aSearchedUids = $this->GetUids($oCacher, $sSearch, $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash); if (\is_array($aSearchedUids) && 0 < \count($aSearchedUids)) { $aFlippedSearchedUids = \array_flip($aSearchedUids); $bSearch = true; $aNewUids = array(); foreach ($aUids as $iUid) { if (isset($aFlippedSearchedUids[$iUid])) { $aNewUids[] = $iUid; } else { if ($bUseThreadSortIfSupported && 0 === $iThreadUid && isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid])) { foreach ($mAllThreads[$iUid] as $iSubUid) { if (isset($aFlippedSearchedUids[$iSubUid])) { $aNewUids[] = $iUid; continue; } } } } } $aUids = \array_unique($aNewUids); unset($aNewUids); } else { $aUids = array(); } } if (\is_array($aUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = \count($aUids); if (0 < \count($aUids)) { $aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); } } } else { if (0 < $iMessageRealCount) { if ($this->oLogger) { $this->oLogger->Write('List optimization (count: ' . $iMessageRealCount . ', limit:' . \MailSo\Config::$MessageListCountLimitTrigger . ')'); } $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; if (0 < \strlen($sSearch) || $bUseFilter) { $aUids = $this->GetUids($oCacher, $sSearch, $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash); if (0 < \count($aUids)) { $oMessageCollection->MessageResultCount = \count($aUids); $aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); } else { $oMessageCollection->MessageResultCount = 0; } } else { $oMessageCollection->MessageResultCount = $iMessageRealCount; if (1 < $iMessageRealCount) { $aRequestIndexes = \array_slice(array_reverse(range(1, $iMessageRealCount)), $iOffset, $iLimit); } else { $aRequestIndexes = \array_slice(array(1), $iOffset, $iLimit); } $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexes, false); } } } if ($bUseThreadSortIfSupported && 0 === $iThreadUid && \is_array($mAllThreads) && 0 < \count($mAllThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($mAllThreads) { $iUid = $oMessage->Uid(); if (isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]) && 0 < \count($mAllThreads[$iUid])) { $aSubThreads = $mAllThreads[$iUid]; \array_unshift($aSubThreads, $iUid); $oMessage->SetThreads(\array_map('trim', $aSubThreads)); unset($aSubThreads); } }); } return $oMessageCollection; }
/** * Creates a new MessageCollection for this group. * * @param $code \string Language code for this collection. * @param $unique \bool Whether to build collection for messages unique to this * group only. * @return MessageCollection */ public function initCollection($code, $unique = false) { if (!$unique) { $definitions = $this->getDefinitions(); } else { $definitions = $this->getUniqueDefinitions(); } $defs = new MessageDefinitions($definitions, $this->getNamespace()); $collection = MessageCollection::newFromDefinitions($defs, $code); foreach ($this->getTags() as $type => $tags) { $collection->setTags($type, $tags); } return $collection; }
/** * Returns translation page with all possible translations replaced in * and ugly translation tags removed. * * @param MessageCollection $collection Collection that holds translated messages. * @return string Whole page as wikitext. */ public function getTranslationPageText($collection) { $text = $this->template; // The source // For finding the messages $prefix = $this->title->getPrefixedDBKey() . '/'; if ($collection instanceof MessageCollection) { $collection->loadTranslations(DB_MASTER); $collection->filter('translated', false); } foreach ($this->sections as $ph => $s) { $sectiontext = null; if (isset($collection[$prefix . $s->id])) { /** * @var TMessage $msg */ $msg = $collection[$prefix . $s->id]; $sectiontext = $msg->translation(); } // Use the original text if no translation is available. // For the source language, this will actually be the source, which // contains variable declarations (tvar) instead of variables ($1). // The getTextWithVariables will convert declarations to normal variables // for us so that the variable substitutions below will also work // for the source language. if ($sectiontext === null || $sectiontext === $s->getText()) { $sectiontext = $s->getTextWithVariables(); } // Substitute variables into section text and substitute text into document $sectiontext = strtr($sectiontext, $s->getVariables()); $text = str_replace($ph, $sectiontext, $text); } $nph = array(); $text = TranslatablePage::armourNowiki($nph, $text); // Remove translation markup from the template to produce final text $cb = array(__CLASS__, 'replaceTagCb'); $text = preg_replace_callback('~(<translate>)(.*)(</translate>)~sU', $cb, $text); $text = TranslatablePage::unArmourNowiki($nph, $text); return $text; }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param mixed $oCacher = null * @param string $sCachePrefix = '' * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array()) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999) || !is_string($sSearch)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $this->oImapClient->FolderExamine($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $aLastCollapsedThreadUids = array(); $aThreads = array(); $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $sSerializedHash = ''; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $iMessageCount = $iMessageRealCount; $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); $bCacher = false; $bSearch = false; if (0 < $iMessageRealCount) { $bIndexAsUid = false; $aIndexOrUids = array(); $bSearch = 0 < \strlen($sSearch); if ($bSearch || $bUseSortIfSupported && !$bUseThreadSortIfSupported) { $bIndexAsUid = true; $aIndexOrUids = null; $sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete(); if ($oCacher && $oCacher->IsInited()) { $sSerializedHash = ($bUseSortIfSupported ? 'S' : 'N') . '/' . ($bUseThreadSortIfSupported ? 'T' : 'N') . '/' . $this->oImapClient->GetLogginedUser() . '@' . $this->oImapClient->GetConnectedHost() . ':' . $this->oImapClient->GetConnectedPort() . '/' . $oMessageCollection->FolderName . '/' . $oMessageCollection->FolderHash . '/' . $sSearchCriterias; $sSerializedUids = $oCacher->Get($sSerializedHash); if (!empty($sSerializedUids)) { $aSerializedUids = @\unserialize($sSerializedUids); if (\is_array($aSerializedUids)) { $aIndexOrUids = $aSerializedUids; $bCacher = true; } } } if (!\is_array($aIndexOrUids)) { if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) { $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); } else { if (!\MailSo\Base\Utils::IsAscii($sSearch)) { try { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { $oException = null; $aIndexOrUids = null; } } if (null === $aIndexOrUids) { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); } } } } else { if ($bUseThreadSortIfSupported && 1 < $iMessageCount) { $bIndexAsUid = true; $aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oCacher); $aIndexOrUids = $this->compileLineThreadUids($aThreads, $aLastCollapsedThreadUids, $aExpandedThreadsUids, 0); $iMessageCount = count($aIndexOrUids); } else { $bIndexAsUid = false; $aIndexOrUids = array(1); if (1 < $iMessageCount) { $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); } } } if ($bIndexAsUid && !$bCacher && \is_array($aIndexOrUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) { $oCacher->Set($sSerializedHash, \serialize($aIndexOrUids)); } if (\is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) ? $iMessageCount : \count($aIndexOrUids); if (0 < count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); } } } $aLastCollapsedThreadUidsForPage = array(); if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) { $iUid = $oMessage->Uid(); if (in_array($iUid, $aLastCollapsedThreadUids)) { $aLastCollapsedThreadUidsForPage[] = $iUid; } if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); $oMessage->SetThreadsLen(\count($aThreads[$iUid])); } else { if (!isset($aThreads[$iUid])) { foreach ($aThreads as $iKeyUid => $mSubItem) { if (is_array($mSubItem) && in_array($iUid, $mSubItem)) { $oMessage->SetParentThread($iKeyUid); $oMessage->SetThreadsLen(\count($mSubItem)); } } } } }); $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; } return $oMessageCollection; }
public function getMessageCollections($userId, $appId, $fields, $options) { // TODO: Supports filtered fields, options. Supports unread and total. $this->checkDb(); $appId = intval($appId); $userId = intval($userId); $countQuery = "select count(*) from message_collections where person_id = {$userId} and app_id = {$appId}"; $res = mysqli_query($this->db, $countQuery); if ($res !== false) { list($totalResults) = mysqli_fetch_row($res); } else { $totalResults = '0'; } $startIndex = $options->getStartIndex(); $count = $options->getCount(); $collections = array(); $collections['totalResults'] = $totalResults; $collections['startIndex'] = $startIndex; $collections['count'] = $count; $query = "select id, title, updated, urls from message_collections where person_id = {$userId} and app_id = {$appId} limit {$startIndex}, {$count}"; $res = mysqli_query($this->db, $query); if ($res) { if (@mysqli_num_rows($res)) { while ($row = @mysqli_fetch_array($res, MYSQLI_ASSOC)) { $collection = new MessageCollection($row['id'], $row['title']); $collection->setUpdated($row['updated']); $collection->setTitle($row['title']); if (isset($row['urls'])) { $collection->setUrls(json_decode($row['urls'])); } $collections[] = $collection; } } return $collections; } else { throw new SocialSpiException("Can't retrieve message collections.", ResponseError::$INTERNAL_ERROR); } }