/**
  * Populates the cache from current state of the source file.
  * @param $created \string Unix timestamp when the cache is created (for automatic updates).
  */
 public function create($created = false)
 {
     $this->close();
     // Close the reader instance just to be sure
     $messages = $this->group->load($this->code);
     if (!count($messages) && !$this->group instanceof SingleFileBasedMessageGroup) {
         if ($this->exists()) {
             // Delete stale cache files
             unlink($this->getCacheFileName());
         }
         return;
         // Don't create empty caches
     }
     $hash = md5(file_get_contents($this->group->getSourceFilePath($this->code)));
     $cache = CdbWriter::open($this->getCacheFileName());
     $keys = array_keys($messages);
     $cache->set('#keys', serialize($keys));
     foreach ($messages as $key => $value) {
         $cache->set($key, $value);
     }
     $cache->set('#created', $created ? $created : wfTimestamp());
     $cache->set('#updated', wfTimestamp());
     $cache->set('#filehash', $hash);
     $cache->set('#msgcount', count($messages));
     ksort($messages);
     $cache->set('#msghash', md5(serialize($messages)));
     $cache->set('#version', '3');
     $cache->close();
 }
 /**
  * Do some conflict resolution for translations.
  * @param string $code Language code.
  * @param bool|int $startTs Time of the last export (changes in wiki after
  * this will conflict)
  * @param bool|int $endTs Time of the last export (changes in source before
  * this won't conflict)
  * @param bool|int $changeTs When change happened in the source.
  */
 public function checkConflicts($code, $startTs = false, $endTs = false, $changeTs = false)
 {
     $messages = $this->group->load($code);
     if (!count($messages)) {
         return;
     }
     $collection = $this->group->initCollection($code);
     $collection->filter('ignored');
     $collection->loadTranslations();
     foreach ($messages as $key => $translation) {
         if (!isset($collection[$key])) {
             continue;
         }
         // @todo Temporary exception. Should be fixed elsewhere more generically.
         if ($translation == '{{PLURAL:GETTEXT|}}') {
             return;
         }
         $title = Title::makeTitleSafe($this->group->getNamespace(), "{$key}/{$code}");
         $page = $title->getPrefixedText();
         if ($collection[$key]->translation() === null) {
             $this->reportProgress("Importing {$page} as a new translation\n", 'importing');
             $this->import($title, $translation, 'Importing a new translation');
             continue;
         }
         $current = str_replace(TRANSLATE_FUZZY, '', $collection[$key]->translation());
         $translation = str_replace(TRANSLATE_FUZZY, '', $translation);
         if ($translation === $current) {
             continue;
         }
         $this->reportProgress("Conflict in " . $this->color('bold', $page) . "!", $page);
         $iso = 'xnY-xnm-xnd"T"xnH:xni:xns';
         $lang = RequestContext::getMain()->getLanguage();
         // Finally all is ok, now lets start comparing timestamps
         // Make sure we are comparing timestamps in same format
         $wikiTs = $this->getLastGoodChange($title, $startTs);
         if ($wikiTs) {
             $wikiTs = wfTimestamp(TS_UNIX, $wikiTs);
             $wikiDate = $lang->sprintfDate($iso, wfTimestamp(TS_MW, $wikiTs));
         } else {
             $wikiDate = 'Unknown';
         }
         if ($startTs) {
             $startTs = wfTimestamp(TS_UNIX, $startTs);
         }
         if ($endTs) {
             $endTs = wfTimestamp(TS_UNIX, $endTs);
         }
         if ($changeTs) {
             $changeTs = wfTimestamp(TS_UNIX, $changeTs);
             $changeDate = $lang->sprintfDate($iso, wfTimestamp(TS_MW, $changeTs));
         } else {
             $changeDate = 'Unknown';
         }
         if ($changeTs) {
             if ($wikiTs > $startTs && $changeTs <= $endTs) {
                 $this->reportProgress(" →Changed in wiki after export: IGNORE", $page);
                 continue;
             } elseif (!$wikiTs || $changeTs > $endTs && $wikiTs < $startTs) {
                 $this->reportProgress(" →Changed in source after export: IMPORT", $page);
                 $this->import($title, $translation, 'Updating translation from external source');
                 continue;
             }
         }
         if (!$this->interactive) {
             continue;
         }
         $this->reportProgress(" →Needs manual resolution", $page);
         $this->reportProgress("Source translation at {$changeDate}:", 'source');
         $this->reportProgress($this->color('blue', $translation), 'source');
         $this->reportProgress("Wiki translation at {$wikiDate}:", 'translation');
         $this->reportProgress($this->color('green', $current), 'translation');
         do {
             $this->reportProgress("Resolution: [S]kip [I]mport [C]onflict: ", 'foo');
             // @todo Find an elegant way to use Maintenance::readconsole().
             $action = fgets(STDIN);
             $action = strtoupper(trim($action));
             if ($action === 'S') {
                 break;
             }
             if ($action === 'I') {
                 $this->import($title, $translation, 'Updating translation from external source');
                 break;
             }
             if ($action === 'C') {
                 $this->import($title, TRANSLATE_FUZZY . $translation, 'Edit conflict between wiki and source');
                 break;
             }
         } while (true);
     }
 }