object = new ExportOdt(); } /** * tearDown for test cases */ protected function tearDown(): void { parent::tearDown(); unset($this->object); } public function testSetProperties(): void { $GLOBALS['plugin_param']['export_type'] = ''; $GLOBALS['plugin_param']['single_table'] = false; $relationParameters = RelationParameters::fromArray([ 'db' => 'db', 'relation' => 'relation', 'column_info' => 'column_info', 'relwork' => true, 'mimework' => true, ]); $_SESSION = ['relation' => [$GLOBALS['server'] => $relationParameters->toArray()]]; $method = new ReflectionMethod(ExportOdt::class, 'setProperties'); $method->setAccessible(true); $properties = $method->invoke($this->object, null); $this->assertInstanceOf(ExportPluginProperties::class, $properties); $this->assertEquals( 'OpenDocument Text', $properties->getText() ); $this->assertEquals( 'odt', $properties->getExtension() ); $this->assertEquals( 'application/vnd.oasis.opendocument.text', $properties->getMimeType() ); $this->assertEquals( 'Options', $properties->getOptionsText() ); $this->assertTrue( $properties->getForceFile() ); $options = $properties->getOptions(); $this->assertInstanceOf(OptionsPropertyRootGroup::class, $options); $this->assertEquals( 'Format Specific Options', $options->getName() ); $generalOptionsArray = $options->getProperties(); $generalOptions = array_shift($generalOptionsArray); $this->assertInstanceOf(OptionsPropertyMainGroup::class, $generalOptions); $this->assertEquals( 'general_opts', $generalOptions->getName() ); $this->assertEquals( 'Dump table', $generalOptions->getText() ); $generalProperties = $generalOptions->getProperties(); $property = array_shift($generalProperties); $this->assertInstanceOf(RadioPropertyItem::class, $property); $this->assertEquals( 'structure_or_data', $property->getName() ); $this->assertEquals( [ 'structure' => __('structure'), 'data' => __('data'), 'structure_and_data' => __('structure and data'), ], $property->getValues() ); $generalOptions = array_shift($generalOptionsArray); $this->assertInstanceOf(OptionsPropertyMainGroup::class, $generalOptions); $this->assertEquals( 'structure', $generalOptions->getName() ); $this->assertEquals( 'Object creation options', $generalOptions->getText() ); $this->assertEquals( 'data', $generalOptions->getForce() ); $generalProperties = $generalOptions->getProperties(); $property = array_shift($generalProperties); $this->assertInstanceOf(BoolPropertyItem::class, $property); $this->assertEquals( 'relation', $property->getName() ); $this->assertEquals( 'Display foreign key relationships', $property->getText() ); $property = array_shift($generalProperties); $this->assertInstanceOf(BoolPropertyItem::class, $property); $this->assertEquals( 'comments', $property->getName() ); $this->assertEquals( 'Display comments', $property->getText() ); $property = array_shift($generalProperties); $this->assertInstanceOf(BoolPropertyItem::class, $property); $this->assertEquals( 'mime', $property->getName() ); $this->assertEquals( 'Display media types', $property->getText() ); // hide structure $generalOptions = array_shift($generalOptionsArray); $this->assertInstanceOf(OptionsPropertyMainGroup::class, $generalOptions); $this->assertEquals( 'data', $generalOptions->getName() ); $this->assertEquals( 'Data dump options', $generalOptions->getText() ); $this->assertEquals( 'structure', $generalOptions->getForce() ); $generalProperties = $generalOptions->getProperties(); $property = array_shift($generalProperties); $this->assertInstanceOf(BoolPropertyItem::class, $property); $this->assertEquals( 'columns', $property->getName() ); $this->assertEquals( 'Put columns names in the first row', $property->getText() ); $property = array_shift($generalProperties); $this->assertInstanceOf(TextPropertyItem::class, $property); $this->assertEquals( 'null', $property->getName() ); $this->assertEquals( 'Replace NULL with:', $property->getText() ); // case 2 $GLOBALS['plugin_param']['export_type'] = 'table'; $GLOBALS['plugin_param']['single_table'] = false; $method->invoke($this->object, null); $generalOptionsArray = $options->getProperties(); $this->assertCount(3, $generalOptionsArray); } public function testExportHeader(): void { $this->assertTrue( $this->object->exportHeader() ); $this->assertStringContainsString('assertStringContainsString('office:version', $GLOBALS['odt_buffer']); } public function testExportFooter(): void { $GLOBALS['odt_buffer'] = 'header'; $this->expectOutputRegex('/^504b.*636f6e74656e742e786d6c/'); $this->setOutputCallback('bin2hex'); $this->assertTrue( $this->object->exportFooter() ); $this->assertStringContainsString('header', $GLOBALS['odt_buffer']); $this->assertStringContainsString( '', $GLOBALS['odt_buffer'] ); } public function testExportDBHeader(): void { $GLOBALS['odt_buffer'] = 'header'; $this->assertTrue( $this->object->exportDBHeader('d&b') ); $this->assertStringContainsString('header', $GLOBALS['odt_buffer']); $this->assertStringContainsString('Database d&b', $GLOBALS['odt_buffer']); } public function testExportDBFooter(): void { $this->assertTrue( $this->object->exportDBFooter('testDB') ); } public function testExportDBCreate(): void { $this->assertTrue( $this->object->exportDBCreate('testDB', 'database') ); } public function testExportData(): void { $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $flags = []; $a = new stdClass(); $flags[] = new FieldMetadata(-1, 0, $a); $a = new stdClass(); $a->charsetnr = 63; $flags[] = new FieldMetadata(MYSQLI_TYPE_BLOB, MYSQLI_BLOB_FLAG, $a); $flags[] = new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_NUM_FLAG, (object) []); $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []); $resultStub = $this->createMock(DummyResult::class); $dbi->expects($this->once()) ->method('getFieldsMeta') ->with($resultStub) ->will($this->returnValue($flags)); $dbi->expects($this->once()) ->method('query') ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->will($this->returnValue($resultStub)); $resultStub->expects($this->once()) ->method('numFields') ->will($this->returnValue(4)); $resultStub->expects($this->exactly(2)) ->method('fetchRow') ->willReturnOnConsecutiveCalls( [ null, 'ab', 'a&b', ], [] ); $GLOBALS['dbi'] = $dbi; $GLOBALS['what'] = 'foo'; $GLOBALS['foo_null'] = '&'; unset($GLOBALS['foo_columns']); $this->assertTrue( $this->object->exportData( 'db', 'taassertEquals( 'Dumping data for table ta<ble' . '' . '&' . '' . 'a>b' . '' . 'a&b' . '', $GLOBALS['odt_buffer'] ); } public function testExportDataWithFieldNames(): void { $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $flags = []; $a = new stdClass(); $a->name = 'fna\"me'; $a->length = 20; $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a); $b = new stdClass(); $b->name = 'fnam/length = 20; $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $b); $resultStub = $this->createMock(DummyResult::class); $dbi->expects($this->once()) ->method('getFieldsMeta') ->with($resultStub) ->will($this->returnValue($flags)); $dbi->expects($this->once()) ->method('query') ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->will($this->returnValue($resultStub)); $resultStub->expects($this->once()) ->method('numFields') ->will($this->returnValue(2)); $resultStub->expects($this->exactly(1)) ->method('fetchRow') ->will($this->returnValue([])); $GLOBALS['dbi'] = $dbi; $GLOBALS['what'] = 'foo'; $GLOBALS['foo_null'] = '&'; $GLOBALS['foo_columns'] = true; $this->assertTrue( $this->object->exportData( 'db', 'table', "\n", 'example.com', 'SELECT' ) ); $this->assertEquals( 'Dumping data for table tablefna\"me' . 'fnam/<e2' . '', $GLOBALS['odt_buffer'] ); // with no row count $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $flags = []; $resultStub = $this->createMock(DummyResult::class); $dbi->expects($this->once()) ->method('getFieldsMeta') ->with($resultStub) ->will($this->returnValue($flags)); $dbi->expects($this->once()) ->method('query') ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->will($this->returnValue($resultStub)); $resultStub->expects($this->once()) ->method('numFields') ->will($this->returnValue(0)); $resultStub->expects($this->once()) ->method('fetchRow') ->will($this->returnValue([])); $GLOBALS['dbi'] = $dbi; $GLOBALS['mediawiki_caption'] = true; $GLOBALS['mediawiki_headers'] = true; $GLOBALS['what'] = 'foo'; $GLOBALS['foo_null'] = '&'; $GLOBALS['odt_buffer'] = ''; $this->assertTrue( $this->object->exportData( 'db', 'table', "\n", 'example.com', 'SELECT' ) ); $this->assertEquals( 'Dumping data for table table' . '' . '', $GLOBALS['odt_buffer'] ); } public function testGetTableDefStandIn(): void { $this->dummyDbi->addSelectDb('test_db'); $this->assertSame( $this->object->getTableDefStandIn('test_db', 'test_table', "\n"), '' ); $this->assertAllSelectsConsumed(); $this->assertEquals( '' . '' . 'Column' . 'Type' . 'Null' . 'Default' . '' . 'id' . 'int(11)' . 'No' . 'NULL' . '' . 'name' . 'varchar(20)' . 'No' . 'NULL' . '' . 'datetimefield' . 'datetime' . 'No' . 'NULL' . '', $GLOBALS['odt_buffer'] ); } public function testGetTableDef(): void { $this->object = $this->getMockBuilder(ExportOdt::class) ->onlyMethods(['formatOneColumnDefinition']) ->getMock(); // case 1 $resultStub = $this->createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects($this->exactly(2)) ->method('fetchResult') ->willReturnOnConsecutiveCalls( [], [ 'fieldname' => [ 'values' => 'test-', 'transformation' => 'testfoo', 'mimetype' => 'test<', ], ] ); $columns = ['Field' => 'fieldname']; $dbi->expects($this->once()) ->method('getColumns') ->with('database', '') ->will($this->returnValue([$columns])); $dbi->expects($this->once()) ->method('tryQueryAsControlUser') ->will($this->returnValue($resultStub)); $resultStub->expects($this->once()) ->method('numRows') ->will($this->returnValue(1)); $resultStub->expects($this->once()) ->method('fetchAssoc') ->will($this->returnValue(['comment' => 'testComment'])); $GLOBALS['dbi'] = $dbi; $this->object->relation = new Relation($dbi); $this->object->expects($this->exactly(2)) ->method('formatOneColumnDefinition') ->with(['Field' => 'fieldname']) ->will($this->returnValue(1)); $_SESSION['relation'] = []; $_SESSION['relation'][$GLOBALS['server']] = RelationParameters::fromArray([ 'relwork' => true, 'commwork' => true, 'mimework' => true, 'db' => 'database', 'relation' => 'rel', 'column_info' => 'col', ])->toArray(); $this->assertTrue( $this->object->getTableDef( 'database', '', "\n", 'example.com', true, true, true ) ); $this->assertStringContainsString( '', $GLOBALS['odt_buffer'] ); $this->assertStringContainsString( 'Comments', $GLOBALS['odt_buffer'] ); $this->assertStringContainsString( 'Media type', $GLOBALS['odt_buffer'] ); $this->assertStringContainsString( '1' . 'Test<' . '', $GLOBALS['odt_buffer'] ); // case 2 $resultStub = $this->createMock(DummyResult::class); $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $dbi->expects($this->exactly(2)) ->method('fetchResult') ->willReturnOnConsecutiveCalls( [ 'fieldname' => [ 'foreign_table' => 'ftable', 'foreign_field' => 'ffield', ], ], [ 'field' => [ 'values' => 'test-', 'transformation' => 'testfoo', 'mimetype' => 'test<', ], ] ); $columns = ['Field' => 'fieldname']; $dbi->expects($this->once()) ->method('getColumns') ->with('database', '') ->will($this->returnValue([$columns])); $dbi->expects($this->once()) ->method('tryQueryAsControlUser') ->will($this->returnValue($resultStub)); $resultStub->expects($this->once()) ->method('numRows') ->will($this->returnValue(1)); $resultStub->expects($this->once()) ->method('fetchAssoc') ->will($this->returnValue(['comment' => 'testComment'])); $GLOBALS['dbi'] = $dbi; $this->object->relation = new Relation($dbi); $GLOBALS['odt_buffer'] = ''; $_SESSION['relation'] = []; $_SESSION['relation'][$GLOBALS['server']] = RelationParameters::fromArray([ 'relwork' => true, 'commwork' => true, 'mimework' => true, 'db' => 'database', 'relation' => 'rel', 'column_info' => 'col', ])->toArray(); $this->assertTrue( $this->object->getTableDef( 'database', '', "\n", 'example.com', true, true, true ) ); $this->assertStringContainsString('ftable (ffield)', $GLOBALS['odt_buffer']); } public function testGetTriggers(): void { $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); $triggers = [ [ 'name' => 'tna"me', 'action_timing' => 'ac>t', 'event_manipulation' => 'manip&', 'definition' => 'def', ], ]; $dbi->expects($this->once()) ->method('getTriggers') ->with('database', 'tawill($this->returnValue($triggers)); $GLOBALS['dbi'] = $dbi; $method = new ReflectionMethod(ExportOdt::class, 'getTriggers'); $method->setAccessible(true); $result = $method->invoke($this->object, 'database', 'taassertSame($result, $GLOBALS['odt_buffer']); $this->assertStringContainsString('', $result); $this->assertStringContainsString('tna"me', $result); $this->assertStringContainsString('ac>t', $result); $this->assertStringContainsString('manip&', $result); $this->assertStringContainsString('def', $result); } public function testExportStructure(): void { // case 1 $this->dummyDbi->addSelectDb('test_db'); $this->assertTrue( $this->object->exportStructure( 'test_db', 'test_table', "\n", 'localhost', 'create_table', 'test' ) ); $this->assertAllSelectsConsumed(); $this->assertEquals( '' . 'Table structure for table test_table' . '' . 'Column' . 'Type' . 'Null' . 'Default' . '' . 'id' . 'int(11)' . 'No' . 'NULL' . '' . 'name' . 'varchar(20)' . 'No' . 'NULL' . '' . 'datetimefield' . 'datetime' . 'No' . 'NULL' . '', $GLOBALS['odt_buffer'] ); // case 2 $GLOBALS['odt_buffer'] = ''; $this->assertTrue( $this->object->exportStructure( 'test_db', 'test_table', "\n", 'localhost', 'triggers', 'test' ) ); $this->assertEquals( '' . 'Triggers test_table' . '' . 'Name' . 'Time' . 'Event' . 'Definition' . '' . 'test_trigger' . 'AFTER' . 'INSERT' . 'BEGIN END' . '', $GLOBALS['odt_buffer'] ); // case 3 $GLOBALS['odt_buffer'] = ''; $this->dummyDbi->addSelectDb('test_db'); $this->assertTrue( $this->object->exportStructure( 'test_db', 'test_table', "\n", 'localhost', 'create_view', 'test' ) ); $this->assertAllSelectsConsumed(); $this->assertEquals( '' . 'Structure for view test_table' . '' . 'Column' . 'Type' . 'Null' . 'Default' . '' . 'id' . 'int(11)' . 'No' . 'NULL' . '' . 'name' . 'varchar(20)' . 'No' . 'NULL' . '' . 'datetimefield' . 'datetime' . 'No' . 'NULL' . '', $GLOBALS['odt_buffer'] ); // case 4 $this->dummyDbi->addSelectDb('test_db'); $GLOBALS['odt_buffer'] = ''; $this->assertTrue( $this->object->exportStructure( 'test_db', 'test_table', "\n", 'localhost', 'stand_in', 'test' ) ); $this->assertAllSelectsConsumed(); $this->assertEquals( '' . 'Stand-in structure for view test_table' . '' . 'Column' . 'Type' . 'Null' . 'Default' . '' . 'id' . 'int(11)' . 'No' . 'NULL' . '' . 'name' . 'varchar(20)' . 'No' . 'NULL' . '' . 'datetimefield' . 'datetime' . 'No' . 'NULL' . '', $GLOBALS['odt_buffer'] ); } public function testFormatOneColumnDefinition(): void { $method = new ReflectionMethod(ExportOdt::class, 'formatOneColumnDefinition'); $method->setAccessible(true); $cols = [ 'Null' => 'Yes', 'Field' => 'field', 'Key' => 'PRI', 'Type' => 'set(abc)enum123', ]; $col_alias = 'alias'; $this->assertEquals( '' . 'aliasset(abc)Yes' . 'NULL', $method->invoke($this->object, $cols, $col_alias) ); $cols = [ 'Null' => 'NO', 'Field' => 'fields', 'Key' => 'COMP', 'Type' => '', 'Default' => 'def', ]; $this->assertEquals( '' . 'fields&nbsp;No' . 'def', $method->invoke($this->object, $cols, '') ); } }