/** * @param string $liftFilePath * @param LexiconProjectModel $projectModel * @param LiftMergeRule $mergeRule * @param boolean $skipSameModTime * @param boolean $deleteMatchingEntry * @return \Api\Model\Languageforge\Lexicon\LiftImport */ public function merge($liftFilePath, $projectModel, $mergeRule = LiftMergeRule::CREATE_DUPLICATES, $skipSameModTime = true, $deleteMatchingEntry = false) { ini_set('max_execution_time', 180); // Sufficient time to import webster. TODO Make this async CP 2014-10 $entryList = new LexEntryListModel($projectModel); $entryList->read(); $hasExistingData = $entryList->count != 0; if (!$hasExistingData) { $projectModel->config->clearAllInputSystems(); // save and clear input systems $savedInputSystems = $projectModel->inputSystems->getArrayCopy(); $projectModel->inputSystems->exchangeArray(array()); } $reader = new \XMLReader(); $reader->open($liftFilePath); $this->liftDecoder = new LiftDecoder($projectModel); $this->stats = new LiftImportStats($entryList->count); $this->report = new ImportErrorReport(); $this->liftImportNodeError = new LiftImportNodeError(LiftImportNodeError::FILE, basename($liftFilePath)); $liftRangeDecoder = new LiftRangeDecoder($projectModel); $liftRangeFiles = array(); // Keys: filenames. Values: parsed files. $liftRanges = array(); // Keys: @id attributes of <range> elements. Values: parsed <range> elements. $liftFolderPath = dirname($liftFilePath); while ($reader->read()) { // Read LIFT ranges in the header of the LIFT file if ($reader->nodeType == \XMLReader::ELEMENT && $reader->localName == 'range') { $node = $reader->expand(); $rangeId = $node->attributes->getNamedItem('id')->textContent; $rangeHref = $node->attributes->getNamedItem('href')->textContent; $hrefPath = parse_url($rangeHref, PHP_URL_PATH); $rangeFilename = basename($hrefPath); $rangeImportNodeError = new LiftRangeImportNodeError(LiftRangeImportNodeError::FILE, $rangeFilename); if (!array_key_exists($rangeFilename, $liftRangeFiles)) { // Haven't parsed the .lift-ranges file yet. We'll assume it is alongside the .lift file. $rangeFilePath = $liftFolderPath . "/" . $rangeFilename; if (file_exists($rangeFilePath)) { $sxeNode = simplexml_load_file($rangeFilePath); $parsedRanges = $liftRangeDecoder->decode($sxeNode); $liftRanges = array_merge($liftRanges, $parsedRanges); $liftRangeFiles[] = $rangeFilename; } else { // Range file was NOT found in alongside the .lift file $rangeImportNodeError->addRangeFileNotFound(basename($liftFilePath)); } } // pull out the referenced range if (isset($liftRanges[$rangeId])) { $range = $liftRanges[$rangeId]; } else { $range = null; if (file_exists($rangeFilePath)) { // Range was NOT found in referenced .lift-ranges file after parsing it $rangeImportNodeError->addRangeNotFound($rangeId); } } // Range elements defined in LIFT file override any values defined in .lift-ranges file. if ($node->hasChildNodes()) { $rangeNode = self::domNode_to_sxeNode($node); $range = $liftRangeDecoder->readRange($rangeNode, $range); $liftRanges[$rangeId] = $range; } if ($rangeImportNodeError->hasErrors()) { $this->liftImportNodeError->addSubnodeError($rangeImportNodeError); } } // Read the custom 'fields' spec in the header of the LIFT file if ($reader->nodeType == \XMLReader::ELEMENT && $reader->localName == 'fields') { $isInFieldsSectionOfLift = true; $this->liftDecoder->liftFields = array(); while ($isInFieldsSectionOfLift && $reader->read()) { if ($reader->nodeType == \XMLReader::ELEMENT && $reader->localName == 'field') { $node = $reader->expand(); $sxeNode = self::domNode_to_sxeNode($node); $LiftFieldTag = (string) $sxeNode['tag']; $liftField = array(); foreach ($sxeNode as $element) { if ($element->getName() === 'form') { $inputSystemTag = (string) $element['lang']; $liftField[$inputSystemTag] = (string) $element->text; } } $this->liftDecoder->liftFields[$LiftFieldTag] = $liftField; } elseif ($reader->nodeType == \XMLReader::END_ELEMENT && $reader->localName == 'fields') { $isInFieldsSectionOfLift = false; } } } // Read an entry node if ($reader->nodeType == \XMLReader::ELEMENT && $reader->localName == 'entry') { $this->stats->importEntries++; $node = $reader->expand(); $sxeNode = self::domNode_to_sxeNode($node); $guid = $reader->getAttribute('guid'); $existingEntry = $entryList->searchEntriesFor('guid', $guid); if ($existingEntry) { $entry = new LexEntryModel($projectModel, $existingEntry['id']); $dateModified = $reader->getAttribute('dateModified'); if (self::differentModTime($dateModified, $entry->authorInfo->modifiedDate) || !$skipSameModTime) { if ($mergeRule == LiftMergeRule::CREATE_DUPLICATES) { $entry = new LexEntryModel($projectModel); $this->readEntryWithErrorReport($sxeNode, $entry, $mergeRule); $entry->guid = ''; $entry->write(); $this->stats->entriesDuplicated++; } else { if (isset($sxeNode->{'lexical-unit'})) { $this->readEntryWithErrorReport($sxeNode, $entry, $mergeRule); $entry->write(); $this->stats->entriesMerged++; } elseif (isset($sxeNode->attributes()->dateDeleted) && $deleteMatchingEntry) { LexEntryModel::remove($projectModel, $existingEntry['id']); $this->stats->entriesDeleted++; } } } else { // skip because same mod time and skip enabled if (!isset($sxeNode->{'lexical-unit'}) && isset($sxeNode->attributes()->dateDeleted) && $deleteMatchingEntry) { LexEntryModel::remove($projectModel, $existingEntry['id']); $this->stats->entriesDeleted++; } } } else { if (isset($sxeNode->{'lexical-unit'})) { $entry = new LexEntryModel($projectModel); $this->readEntryWithErrorReport($sxeNode, $entry, $mergeRule); $entry->write(); $this->stats->newEntries++; } } } } $reader->close(); // put back saved input systems if none found in the imported data if (!$hasExistingData && $projectModel->inputSystems->count() <= 0) { $projectModel->inputSystems->exchangeArray($savedInputSystems); } // add lift ranges if ($mergeRule != LiftMergeRule::IMPORT_LOSES) { foreach ($liftRanges as $liftRangeCode => $liftRange) { // add everything except semantic domains if (strpos($liftRangeCode, 'semantic-domain') === false) { self::rangeToOptionList($projectModel, $liftRangeCode, LexiconConfigObj::flexOptionlistName($liftRangeCode), $liftRange); } } } $this->report->nodeErrors[] = $this->liftImportNodeError; if ($this->report->hasError()) { error_log($this->report->toString()); } return $this; }
/** * @param string $projectId * @param string $missingInfo - if empty, returns all entries. * if matches one of LexConfig constants (e.g. POS, DEFINITION, etc), then return a subset of entries that have one or more senses missing the specified field * @return LexEntryListModel */ public static function listEntries($projectId, $missingInfo = '') { $project = new LexProjectModel($projectId); $lexEntries = new LexEntryListModel($project); $lexEntries->readForDto($missingInfo); return $lexEntries; }
public function testLiftImportMerge_ZipFileWithDir_CorrectValues() { $zipFilePath = self::$environ->copyTestUploadFile(TestPhpPath . 'common/TestLexProjectWithDir.zip'); $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $importer = LiftImport::get()->importZip($zipFilePath, $project); $entryList = new LexEntryListModel($project); $entryList->read(); $entries = $entryList->entries; $this->assertEquals(2, $entryList->count); $entriesByGuid = self::$environ->indexItemsBy($entries, 'guid'); $entry0 = $entriesByGuid['dd15cbc4-9085-4d66-af3d-8428f078a7da']; $entry1 = $entriesByGuid['05473cb0-4165-4923-8d81-02f8b8ed3f26']; $this->assertEquals('dd15cbc4-9085-4d66-af3d-8428f078a7da', $entry0['guid']); $this->assertEquals('chùuchìi mǔu krɔ̂ɔp', $entry0['lexeme']['th-fonipa']['value']); $this->assertEquals('ฉู่ฉี่หมูกรอบ', $entry0['lexeme']['th']['value']); $this->assertCount(1, $entry0['senses']); $this->assertEquals('incorrect definition', $entry0['senses'][0]['definition']['en']['value']); $this->assertEquals('incorrect gloss', $entry0['senses'][0]['gloss']['en']['value']); $this->assertEquals('th incorrect gloss', $entry0['senses'][0]['gloss']['th']['value']); $this->assertEquals('Adjective', $entry0['senses'][0]['partOfSpeech']['value']); $this->assertEquals('5.2', $entry0['senses'][0]['semanticDomain']['values'][0]); $this->assertEquals('1', $entry0['senses'][0]['semanticDomain']['values'][1]); $this->assertEquals('sentence 1', $entry0['senses'][0]['examples'][0]['sentence']['th-fonipa']['value']); $this->assertEquals('translation 1', $entry0['senses'][0]['examples'][0]['translation']['en']['value']); $this->assertEquals('sentence 2', $entry0['senses'][0]['examples'][1]['sentence']['th-fonipa']['value']); $this->assertEquals('translation 2', $entry0['senses'][0]['examples'][1]['translation']['en']['value']); $this->assertEquals('05473cb0-4165-4923-8d81-02f8b8ed3f26', $entry1['guid']); $this->assertEquals('khâaw kài thɔ̀ɔt', $entry1['lexeme']['th-fonipa']['value']); $this->assertEquals('ข้าวไก่ทอด', $entry1['lexeme']['th']['value']); $this->assertEquals(false, $importer->getReport()->hasError()); }
public function testLiftImportMerge_MultiPara_ParagraphMarkerFound() { $liftFilePath = self::$environ->createTestLiftFile(self::liftOneEntryMultiParaV0_13, 'LiftOneEntryMultiParaV0_13.lift'); $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $mergeRule = LiftMergeRule::IMPORT_WINS; $skipSameModTime = false; LiftImport::get()->merge($liftFilePath, $project, $mergeRule, $skipSameModTime); $entryList = new LexEntryListModel($project); $entryList->read(); $entry0 = $entryList->entries[0]; $this->assertEquals(1, $entryList->count); $this->assertArrayHasKey('customField_entry_Cust_MultiPara', $entry0['customFields'], 'custom field MultiPara exists'); $this->assertEquals('First paragraph with <span lang="th">ไทย</span>', $entry0['customFields']['customField_entry_Cust_MultiPara']['paragraphs'][0]['content'], 'custom field MultiPara has paragraphs separated into paragraph 1 and native language spans removed'); $this->assertEquals('Second Paragraph', $entry0['customFields']['customField_entry_Cust_MultiPara']['paragraphs'][1]['content'], 'custom field MultiPara has paragraphs separated into paragraph 2 and native language spans removed'); }
public function testLiftImportMerge_FlexAllFields_HasAllFields() { $liftFilePath = self::$environ->createTestLiftFile(self::liftAllFlexFields, 'LiftAllFlexFields.lift'); $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $mergeRule = LiftMergeRule::IMPORT_WINS; $skipSameModTime = false; LiftImport::get()->merge($liftFilePath, $project, $mergeRule, $skipSameModTime); $entryList = new LexEntryListModel($project); $entryList->read(); $entries = $entryList->entries; $this->assertEquals(2, $entryList->count); $entriesByGuid = self::$environ->indexItemsBy($entries, 'guid'); $entry0 = new LexEntryModel($project, $entriesByGuid['0a18bb95-0eb2-422e-bf7e-c1fd90274670']['id']); new LexEntryModel($project, $entriesByGuid['dc4106ac-13fd-4ae0-a32b-b737f413d515']['id']); $this->assertEquals('0a18bb95-0eb2-422e-bf7e-c1fd90274670', $entry0->guid); $this->assertEquals('คาม', $entry0->lexeme['th']); $this->assertEquals('คาม', $entry0->citationForm['th']); $this->assertEquals('คาม', $entry0->etymology['th']); $this->assertEquals('A Etymology', $entry0->etymology['en']); $this->assertEquals('A Etymology Gloss', $entry0->etymologyGloss['en']); $this->assertEquals('A Etymology Comment', $entry0->etymologyComment['en']); $this->assertEquals('คาม', $entry0->pronunciation['th']); $this->assertEquals('stem', $entry0->morphologyType); $this->assertEquals('A Literal Meaning', $entry0->literalMeaning['en']); /* @var $sense00 LexSense */ $sense00 = $entry0->senses[0]; $this->assertEquals('Noun', $sense00->partOfSpeech->value); $this->assertEquals('A Word', $sense00->gloss['en']->value); $this->assertEquals('A Word Defn', $sense00->definition['en']->value); $this->assertEquals(LexMultiValue::createFromArray(['9.1.3.1']), $sense00->semanticDomain); $this->assertEquals(LexMultiValue::createFromArray(['901']), $sense00->anthropologyCategories); $this->assertEquals(LexMultiValue::createFromArray(['applied linguistics']), $sense00->academicDomains); $this->assertEquals(new LexValue('primary'), $sense00->senseType); $this->assertEquals(LexMultiValue::createFromArray(['Tentative']), $sense00->status); $this->assertEquals(LexMultiValue::createFromArray(['colloquial']), $sense00->usages); $expected = new LexPicture('Desert.jpg', $sense00->pictures[0]->guid); $expected->caption['th'] = 'รูป'; $expected->caption['en'] = 'image'; $expected->caption['fr'] = 'photo'; $this->assertEquals($expected, $sense00->pictures[0]); /* @var $example000 LexExample */ $example000 = $sense00->examples[0]; $this->assertEquals('ใหท่ มี', $example000->sentence['th']); $this->assertEquals('A Translation', $example000->translation['en']->value); }
public function testImportProjectZip_7zFile_StatsOkAndCustomFieldsImported() { $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $projectId = $project->id->asString(); $fileName = 'TestLangProj.7z'; // Ken Zook's test data $tmpFilePath = $this->environ->uploadFile(TestPath . "common/{$fileName}", $fileName); $userId = $this->environ->createUser('bob', 'bob', '*****@*****.**'); $project->addUser($userId, LexiconRoles::OBSERVER); $project->config->userViews[$userId] = clone $project->config->roleViews[LexiconRoles::OBSERVER]; $project->write(); $this->assertFalse($project->config->entry->fieldOrder->array_search('customField_entry_Cust_Single_Line_All'), "custom field entry config doesn't yet exist"); $this->assertFalse(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->entry->fields), "custom field entry config doesn't yet exist"); $this->assertFalse(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->roleViews[LexiconRoles::OBSERVER]->fields), "custom field roleView config doesn't yet exist"); $this->assertFalse(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->roleViews[LexiconRoles::MANAGER]->fields), "custom field roleView config doesn't yet exist"); $this->assertFalse(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->userViews[$userId]->fields), "custom field userView config doesn't yet exist"); $response = LexUploadCommands::importProjectZip($projectId, 'import-zip', $tmpFilePath); $project->read($project->id->asString()); $filePath = $project->getAssetsFolderPath() . '/' . $response->data->fileName; $projectSlug = $project->databaseName(); $entryList = new LexEntryListModel($project); $entryList->read(); $entries = $entryList->entries; $entriesByGuid = $this->environ->indexItemsBy($entries, 'guid'); $entryA = $entriesByGuid['05c54cf0-4e5a-4bf2-99f8-ec787e4113ac']; $entryB = $entriesByGuid['1a705846-a814-4289-8594-4b874faca6cc']; $entryBSensesByLiftId = $this->environ->indexItemsBy($entryB['senses'], 'liftId'); $entryBSenseA = $entryBSensesByLiftId['eea9c29f-244f-4891-81db-c8274cd61f0c']; $optionListList = new LexOptionListListModel($project); $optionListList->read(); $optionListByCodes = $this->environ->indexItemsBy($optionListList->entries, 'code'); // stats OK? $this->assertTrue($response->result, 'Import should succeed'); $this->assertPattern("/lexicon\\/{$projectSlug}/", $response->data->path, 'Uploaded zip file path should be in the right location'); $this->assertEqual($fileName, $response->data->fileName, 'Uploaded zip fileName should have the original fileName'); $this->assertTrue(file_exists($filePath), 'Uploaded zip file should exist'); $this->assertEqual($response->data->stats->existingEntries, 0); $this->assertEqual($response->data->stats->importEntries, 64); $this->assertEqual($response->data->stats->newEntries, 64); $this->assertEqual($response->data->stats->entriesMerged, 0); $this->assertEqual($response->data->stats->entriesDuplicated, 0); $this->assertEqual($response->data->stats->entriesDeleted, 0); // custom fields imported? $this->assertEqual($entryList->count, 64); $this->assertEqual($optionListList->count, 24); $this->assertTrue(array_key_exists('grammatical-info', $optionListByCodes)); $this->assertFalse(array_key_exists('semantic-domain-ddp4', $optionListByCodes)); $this->assertEqual($entryA['lexeme']['qaa-fonipa-x-kal']['value'], '-kes'); $this->assertEqual($entryA['customFields']['customField_entry_Cust_Single_Line_All']['en']['value'], '635459584141806142kes.wav'); $this->assertTrue($project->config->entry->fieldOrder->array_search('customField_entry_Cust_Single_Line_All'), "custom field entry config exists"); $this->assertTrue(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->entry->fields), "custom field entry config exists"); $this->assertEqual($project->config->entry->fields['customField_entry_Cust_Single_Line_All']->label, 'Cust Single Line All'); $this->assertEqual($project->config->entry->fields['customField_entry_Cust_Single_Line_All']->type, 'multitext'); $this->assertTrue($project->config->entry->fields['customField_entry_Cust_Single_Line_All']->inputSystems->array_search('en')); $this->assertTrue(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->roleViews[LexiconRoles::OBSERVER]->fields), "custom field roleView config exists"); $this->assertTrue(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->roleViews[LexiconRoles::MANAGER]->fields), "custom field roleView config exists"); $this->assertTrue($project->config->roleViews[LexiconRoles::OBSERVER]->fields['customField_entry_Cust_Single_Line_All']->show); $this->assertTrue($project->config->roleViews[LexiconRoles::MANAGER]->fields['customField_entry_Cust_Single_Line_All']->show); $this->assertTrue(array_key_exists('customField_entry_Cust_Single_Line_All', $project->config->userViews[$userId]->fields), "custom field userView config doesn't yet exist"); $this->assertTrue($project->config->userViews[$userId]->fields['customField_entry_Cust_Single_Line_All']->show); $this->assertEqual($entryB['lexeme']['qaa-fonipa-x-kal']['value'], 'zitʰɛstmen'); $this->assertEqual($entryB['customFields']['customField_entry_Cust_Single_ListRef']['value'], 'comparative linguistics'); $this->assertEqual(count($entryBSenseA['customFields']['customField_senses_Cust_Multi_ListRef']['values']), 2); $this->assertEqual($entryBSenseA['customFields']['customField_senses_Cust_Multi_ListRef']['values'][0], 'First Custom Item'); $this->assertEqual($entryBSenseA['customFields']['customField_senses_Cust_Multi_ListRef']['values'][1], 'Second Custom Item'); $this->assertEqual($entryBSenseA['examples'][0]['customFields']['customField_examples_Cust_Example']['qaa-x-kal']['value'], 'Custom example'); /* echo '<pre style="height:500px; overflow:auto">'; echo $response->data->importErrors; echo '</pre>'; */ }
public static function encode($projectId, $userId, $lastFetchTime = null, $offset = 0) { $data = array(); $project = new LexiconProjectModel($projectId); if ($lastFetchTime) { $entriesModel = new LexEntryListModel($project, $lastFetchTime); $entriesModel->readForDto(); $commentsModel = new LexCommentListModel($project, $lastFetchTime); $commentsModel->readAsModels(); } else { $entriesModel = new LexEntryListModel($project, null, self::MAX_ENTRIES_PER_REQUEST, $offset); $entriesModel->readForDto(); $commentsModel = new LexCommentListModel($project, null, self::MAX_ENTRIES_PER_REQUEST, $offset); $commentsModel->readAsModels(); $data['itemTotalCount'] = $entriesModel->totalCount > $commentsModel->totalCount ? $entriesModel->totalCount : $commentsModel->totalCount; $data['itemCount'] = $entriesModel->count > $commentsModel->count ? $entriesModel->count : $commentsModel->count; $data['offset'] = $offset; } $entries = $entriesModel->entries; $encodedComments = LexDbeDtoCommentsEncoder::encode($commentsModel); $data['comments'] = $encodedComments['entries']; /* $commentsModel->read(); $data['comments'] = $commentsModel->entries; */ $votes = new UserGenericVoteModel($userId, $projectId, 'lexCommentPlusOne'); $votesDto = array(); foreach ($votes->votes as $vote) { $votesDto[$vote->ref->id] = true; } $data['commentsUserPlusOne'] = $votesDto; if (!is_null($lastFetchTime)) { $deletedEntriesModel = new LexDeletedEntryListModel($project, $lastFetchTime); $deletedEntriesModel->read(); $data['deletedEntryIds'] = array_map(function ($e) { return $e['id']; }, $deletedEntriesModel->entries); $deletedCommentsModel = new LexDeletedCommentListModel($project, $lastFetchTime); $deletedCommentsModel->read(); $data['deletedCommentIds'] = array_map(function ($c) { return $c['id']; }, $deletedCommentsModel->entries); } $lexemeInputSystems = $project->config->entry->fields[LexiconConfigObj::LEXEME]->inputSystems; usort($entries, function ($a, $b) use($lexemeInputSystems) { $lexeme1 = $a[LexiconConfigObj::LEXEME]; $lexeme1Value = ''; foreach ($lexemeInputSystems as $ws) { if (array_key_exists($ws, $lexeme1) && $lexeme1[$ws]['value'] != '') { $lexeme1Value = $lexeme1[$ws]['value']; // '\P{xx} matches all characters without the Unicode property XX. L is the Unicode property "letter". $lexeme1Value = preg_replace('/^\\P{L}+/', '', $lexeme1Value); // Strip non-letter characters from front of word for sorting break; } } $lexeme2 = $b[LexiconConfigObj::LEXEME]; $lexeme2Value = ''; foreach ($lexemeInputSystems as $ws) { if (array_key_exists($ws, $lexeme2) && $lexeme2[$ws]['value'] != '') { $lexeme2Value = $lexeme2[$ws]['value']; $lexeme2Value = preg_replace('/^\\P{L}+/', '', $lexeme2Value); // Strip non-letter characters from front of word for sorting break; } } return strtolower($lexeme1Value) > strtolower($lexeme2Value) ? 1 : -1; }); $data['entries'] = $entries; $data['timeOnServer'] = time(); // for offline syncing return $data; }
public function testLiftImportMerge_ZipFileWithDir_CorrectValues() { $zipFilePath = $this->environ->copyTestUploadFile(TestPath . 'common/TestLexProjectWithDir.zip'); $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $importer = LiftImport::get()->importZip($zipFilePath, $project); $entryList = new LexEntryListModel($project); $entryList->read(); $entries = $entryList->entries; $this->assertEqual($entryList->count, 2); $entriesByGuid = $this->environ->indexItemsBy($entries, 'guid'); $entry0 = $entriesByGuid['dd15cbc4-9085-4d66-af3d-8428f078a7da']; $entry1 = $entriesByGuid['05473cb0-4165-4923-8d81-02f8b8ed3f26']; $this->assertEqual($entry0['guid'], "dd15cbc4-9085-4d66-af3d-8428f078a7da"); $this->assertEqual($entry0['lexeme']['th-fonipa']['value'], "chùuchìi mǔu krɔ̂ɔp"); $this->assertEqual($entry0['lexeme']['th']['value'], "ฉู่ฉี่หมูกรอบ"); $this->assertEqual(count($entry0['senses']), 1); $this->assertEqual($entry0['senses'][0]['definition']['en']['value'], "incorrect definition"); $this->assertEqual($entry0['senses'][0]['gloss']['en']['value'], "incorrect gloss"); $this->assertEqual($entry0['senses'][0]['gloss']['th']['value'], "th incorrect gloss"); $this->assertEqual($entry0['senses'][0]['partOfSpeech']['value'], "Adjective"); $this->assertEqual($entry0['senses'][0]['semanticDomain']['values'][0], "5.2 Food"); $this->assertEqual($entry0['senses'][0]['semanticDomain']['values'][1], "1 Universe, creation"); $this->assertEqual($entry0['senses'][0]['examples'][0]['sentence']['th-fonipa']['value'], "sentence 1"); $this->assertEqual($entry0['senses'][0]['examples'][0]['translation']['en']['value'], "translation 1"); $this->assertEqual($entry0['senses'][0]['examples'][1]['sentence']['th-fonipa']['value'], "sentence 2"); $this->assertEqual($entry0['senses'][0]['examples'][1]['translation']['en']['value'], "translation 2"); $this->assertEqual($entry1['guid'], "05473cb0-4165-4923-8d81-02f8b8ed3f26"); $this->assertEqual($entry1['lexeme']['th-fonipa']['value'], "khâaw kài thɔ̀ɔt"); $this->assertEqual($entry1['lexeme']['th']['value'], "ข้าวไก่ทอด"); $this->assertFalse($importer->getReport()->hasError()); }
public function testLiftImportMerge_MultiPara_ParagraphMarkerFound() { $liftFilePath = $this->environ->createTestLiftFile(self::liftOneEntryMultiParaV0_13, 'LiftOneEntryMultiParaV0_13.lift'); $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $mergeRule = LiftMergeRule::IMPORT_WINS; $skipSameModTime = false; $importer = LiftImport::get()->merge($liftFilePath, $project, $mergeRule, $skipSameModTime); $entryList = new LexEntryListModel($project); $entryList->read(); $entry0 = $entryList->entries[0]; $this->assertEqual($entryList->count, 1); $this->assertTrue(array_key_exists('customField_entry_Cust_MultiPara', $entry0['customFields']), 'custom field MultiPara exists'); $this->assertEqual($entry0['customFields']['customField_entry_Cust_MultiPara']['en']['value'], '<p>First paragraph with <span lang="th">ไทย</span></p><p>Second Paragraph</p>', 'custom field MultiPara has paragraph separator character U+2029 replaced by paragraph markup and native language spans removed'); }