[BUGFIX] RTE: Empty paragraphs are not correctly transformed 01/18801/3
authorStanislas Rolland <typo3@sjbr.ca>
Fri, 25 May 2012 17:17:53 +0000 (13:17 -0400)
committerStanislas Rolland <typo3@sjbr.ca>
Fri, 8 Mar 2013 19:15:15 +0000 (20:15 +0100)
Problem: Empty paragraphs entered in the RTE may get lost on way to
database if no block is found in content, as well as on way to the RTE
if followed by a block.
Solution: Fix both transformations and add multiple unit test cases.

Change-Id: I6c5495fb668f29267bcdeb7b44814a4bb9dc0f96
Releases: 4.5, 4.7, 6.0, 6.1
Resolves: #36904
Reviewed-on: https://review.typo3.org/18801
Reviewed-by: Stanislas Rolland
Tested-by: Stanislas Rolland
t3lib/class.t3lib_parsehtml_proc.php
tests/t3lib/class.t3lib_parsehtml_procTest.php

index f1636a7..b0b2a64 100644 (file)
@@ -285,8 +285,13 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                                                break;
                                                case 'ts_transform':
                                                case 'css_transform':
-                                                       $value = str_replace(CR, '', $value); // Has a very disturbing effect, so just remove all '13' - depend on '10'
                                                        $this->allowedClasses = t3lib_div::trimExplode(',', $this->procOptions['allowedClasses'], 1);
+                                                               // CR has a very disturbing effect, so just remove all CR and rely on LF
+                                                       $value = str_replace(CR, '', $value);
+                                                               // Transform empty paragraphs into spacing paragraphs
+                                                       $value = str_replace('<p></p>', '<p>&nbsp;</p>', $value);
+                                                               // Double any trailing spacing paragraph so that it does not get removed by divideIntoLines()
+                                                       $value = preg_replace('/<p>&nbsp;<\/p>$/', '<p>&nbsp;</p>' . '<p>&nbsp;</p>', $value);
                                                        $value = $this->TS_transform_db($value, $cmd == 'css_transform');
                                                break;
                                                case 'ts_strip':
@@ -957,10 +962,9 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
         * @see TS_transform_db()
         */
        function TS_transform_rte($value, $css = 0) {
-
-                       // Split the content from Database by the occurence of these blocks:
-               $blockSplit = $this->splitIntoBlock('TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,' . ($this->procOptions['preserveDIVSections'] ? 'DIV,' : '') . $this->blockElementList, $value);
-
+                       // Split the content from database by the occurence of the block elements
+               $blockElementList = 'TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,' . ($this->procOptions['preserveDIVSections'] ? 'DIV,' : '') . $this->blockElementList;
+               $blockSplit = $this->splitIntoBlock($blockElementList, $value);
                        // Traverse the blocks
                foreach ($blockSplit as $k => $v) {
                        if ($k % 2) { // Inside one of the blocks:
@@ -1009,12 +1013,19 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                                $blockSplit[$k + 1] = preg_replace('/^[ ]*' . LF . '/', '', $blockSplit[$k + 1]); // Removing linebreak if typohead
                        } else { // NON-block:
                                $nextFTN = $this->getFirstTagName($blockSplit[$k + 1]);
-                               $singleLineBreak = $blockSplit[$k] == LF;
-                               if (t3lib_div::inList('TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,' . ($this->procOptions['preserveDIVSections'] ? 'DIV,' : '') . $this->blockElementList, $nextFTN)) { // Removing linebreak if typolist/typohead
-                                       $blockSplit[$k] = preg_replace('/' . LF . '[ ]*$/', '', $blockSplit[$k]);
+                               $onlyLineBreaks = (preg_match('/^[ ]*' . LF . '+[ ]*$/', $blockSplit[$k]) == 1);
+                                       // If the line is followed by a block or is the last line:
+                               if (t3lib_div::inList($blockElementList, $nextFTN) || !isset($blockSplit[$k + 1])) {
+                                               // If the line contains more than just linebreaks, reduce the number of trailing linebreaks by 1
+                                       if (!$onlyLineBreaks) {
+                                               $blockSplit[$k] = preg_replace('/(' . LF . '*)' . LF . '[ ]*$/', '$1', $blockSplit[$k]);
+                                       } else {
+                                                       // If the line contains only linebreaks, remove the leading linebreak
+                                               $blockSplit[$k] = preg_replace('/^[ ]*' . LF . '/', '', $blockSplit[$k]);
+                                       }
                                }
-                                       // If $blockSplit[$k] is blank then unset the line. UNLESS the line happend to be a single line break.
-                               if (!strcmp($blockSplit[$k], '') && !$singleLineBreak) {
+                                       // If $blockSplit[$k] is blank then unset the line, unless the line only contained linebreaks
+                               if (!strcmp($blockSplit[$k], '') && !$onlyLineBreaks) {
                                        unset($blockSplit[$k]);
                                } else {
                                        $blockSplit[$k] = $this->setDivTags($blockSplit[$k], ($this->procOptions['useDIVasParagraphTagForRTE'] ? 'div' : 'p'));
@@ -1640,7 +1651,6 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
        }
 }
 
-
 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml_proc.php'])) {
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml_proc.php']);
 }
index 1fd7398..8359472 100644 (file)
@@ -42,72 +42,75 @@ class t3lib_parsehtml_procTest extends tx_phpunit_testcase {
                        'dontConvBRtoParagraph' => '1',
                        'preserveDIVSections' => '1',
                        'allowTagsOutside' => 'hr, address',
+                       'disableUnifyLineBreaks' => '0',
+                       'overruleMode' => 'ts_css',
                );
        }
 
        public function tearDown() {
                unset($this->fixture);
        }
+
        /**
-        * Data provider for TS_transform_db
+        * Data provider for hrTagCorrectlyTransformedOnWayToDataBase
         */
        public static function hrTagCorrectlyTransformedOnWayToDataBaseDataProvider() {
                return array(
-                       'single hr' => array(
+                       'Single hr' => array(
                                '<hr />',
                                '<hr />',
                        ),
-                       'non-xhtml single hr' => array(
+                       'Non-xhtml single hr' => array(
                                '<hr/>',
                                '<hr />',
                        ),
-                       'double hr' => array(
+                       'Double hr' => array(
                                '<hr /><hr />',
-                               '<hr />' . LF . '<hr />',
+                               '<hr />' . CRLF . '<hr />',
                        ),
-                       'linefeed followed by hr' => array(
-                               LF . '<hr />',
+                       'Linebreak followed by hr' => array(
+                               CRLF . '<hr />',
                                '<hr />',
                        ),
-                       'white space followed by hr' => array(
+                       'White space followed by hr' => array(
                                ' <hr />',
-                               ' ' . LF . '<hr />',
+                               ' ' . CRLF . '<hr />',
                        ),
-                       'white space followed linefeed and hr' => array(
-                               ' ' . LF . '<hr />',
-                               ' ' . LF . '<hr />',
+                       'White space followed linebreak and hr' => array(
+                               ' ' . CRLF . '<hr />',
+                               ' ' . CRLF . '<hr />',
                        ),
                        'br followed by hr' => array(
                                '<br /><hr />',
-                               '<br />' . LF . '<hr />',
+                               '<br />' . CRLF . '<hr />',
                        ),
-                       'br followed by linefeed and hr' => array(
-                               '<br />' . LF . '<hr />',
-                               '<br />' . LF . '<hr />',
+                       'br followed by linebreak and hr' => array(
+                               '<br />' . CRLF . '<hr />',
+                               '<br />' . CRLF . '<hr />',
                        ),
-                       'preserved div followed by hr' => array(
+                       'Preserved div followed by hr' => array(
                                '<div>Some text</div><hr />',
-                               '<div>Some text</div>' . LF . '<hr />',
+                               '<div>Some text</div>' . CRLF . '<hr />',
                        ),
-                       'preserved div followed by linefeed and hr' => array(
-                               '<div>Some text</div>' . LF . '<hr />',
-                               '<div>Some text</div>' . LF . '<hr />',
+                       'Preserved div followed by linebreak and hr' => array(
+                               '<div>Some text</div>' . CRLF . '<hr />',
+                               '<div>Some text</div>' . CRLF . '<hr />',
                        ),
-                       'h1 followed by linefeed and hr' => array(
-                               '<h1>Some text</h1>' . LF . '<hr />',
-                               '<h1>Some text</h1>' . LF . '<hr />',
+                       'h1 followed by linebreak and hr' => array(
+                               '<h1>Some text</h1>' . CRLF . '<hr />',
+                               '<h1>Some text</h1>' . CRLF . '<hr />',
                        ),
-                       'paragraph followed by linefeed and hr' => array(
-                               '<p>Some text</p>' . LF . '<hr />',
-                               'Some text' . LF . '<hr />',
+                       'Paragraph followed by linebreak and hr' => array(
+                               '<p>Some text</p>' . CRLF . '<hr />',
+                               'Some text' . CRLF . '<hr />',
                        ),
-                       'some text followed by hr' => array(
+                       'Some text followed by hr' => array(
                                'Some text<hr />',
-                               'Some text' . LF . '<hr />',
+                               'Some text' . CRLF . '<hr />',
                        ),
-                       'some text followed by linefeed and hr' => array(
-                               'Some text' . LF . '<hr />',
-                               'Some text' . LF . '<hr />',
+                       'Some text followed by linebreak and hr' => array(
+                               'Some text' . CRLF . '<hr />',
+                               'Some text' . CRLF . '<hr />',
                        ),
                );
        }
@@ -117,8 +120,520 @@ class t3lib_parsehtml_procTest extends tx_phpunit_testcase {
         * @dataProvider hrTagCorrectlyTransformedOnWayToDataBaseDataProvider
         */
        public function hrTagCorrectlyTransformedOnWayToDataBase($content, $expectedResult) {
-                       // Assume the transformation is ts_css
-               $this->assertEquals($expectedResult, $this->fixture->TS_transform_db($content, TRUE));
+               $thisConfig = array('proc.' => $this->fixture->procOptions);
+               $this->assertEquals($expectedResult, $this->fixture->RTE_transform($content, array(), 'db', $thisConfig));
+       }
+
+       /**
+        * Data provider for hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
+        */
+       public static function hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider() {
+               return array(
+                       'Single hr' => array(
+                               '<hr />',
+                               '<hr />',
+                       ),
+                       'Non-xhtml single hr' => array(
+                               '<hr/>',
+                               '<hr />',
+                       ),
+                       'Double hr' => array(
+                               '<hr /><hr />',
+                               '<hr />' . CRLF . '<hr />',
+                       ),
+                       'Linebreak followed by hr' => array(
+                               CRLF . '<hr />',
+                               '<hr />',
+                       ),
+                       'White space followed by hr' => array(
+                               ' <hr />',
+                               '<p>&nbsp;</p>' . CRLF . '<hr />',
+                       ),
+                       'White space followed by linebreak and hr' => array(
+                               ' ' . CRLF . '<hr />',
+                               '<p>&nbsp;</p>' . CRLF . '<hr />',
+                       ),
+                       'br followed by hr' => array(
+                               '<br /><hr />',
+                               '<p><br /></p>' . CRLF . '<hr />',
+                       ),
+                       'br followed by linebreak and hr' => array(
+                               '<br />' . CRLF . '<hr />',
+                               '<p><br /></p>' . CRLF . '<hr />',
+                       ),
+                       'Preserved div followed by hr' => array(
+                               '<div>Some text</div>' . '<hr />',
+                               '<div><p>Some text</p></div>' . CRLF . '<hr />',
+                       ),
+                       'Preserved div followed by linebreak and hr' => array(
+                               '<div>Some text</div>' . CRLF . '<hr />',
+                               '<div><p>Some text</p></div>' . CRLF . '<hr />',
+                       ),
+                       'h1 followed by linebreak and hr' => array(
+                               '<h1>Some text</h1>' . CRLF . '<hr />',
+                               '<h1>Some text</h1>' . CRLF . '<hr />',
+                       ),
+                       'Paragraph followed by linebreak and hr' => array(
+                               '<p>Some text</p>' . CRLF . '<hr />',
+                               '<p>Some text</p>' . CRLF . '<hr />',
+                       ),
+                       'Some text followed by hr' => array(
+                               'Some text<hr />',
+                               '<p>Some text</p>' . CRLF . '<hr />',
+                       ),
+                       'Some text followed by linebreak and hr' => array(
+                               'Some text' . CRLF . '<hr />',
+                               '<p>Some text</p>' . CRLF . '<hr />',
+                       ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
+        */
+       public function hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult) {
+               $thisConfig = array('proc.' => $this->fixture->procOptions);
+               $this->assertEquals($expectedResult, $this->fixture->RTE_transform($this->fixture->RTE_transform($content, array(), 'db', $thisConfig), array(), 'rte', $thisConfig));
+       }
+
+       /**
+        * Data provider for paragraphCorrectlyTransformedOnWayToDatabase
+        */
+       public static function paragraphCorrectlyTransformedOnWayToDatabaseProvider() {
+               return array(
+                       'Empty string' => array(
+                               '',
+                               '',
+                       ),
+                       'Linebreak' => array(
+                               CRLF,
+                               '',
+                       ),
+                       'Double linebreak' => array(
+                               CRLF . CRLF,
+                               '',
+                       ),
+                       'Empty paragraph' => array(
+                               '<p></p>',
+                               CRLF,
+                       ),
+                       'Double empty paragraph' => array(
+                               '<p></p><p></p>',
+                               CRLF . CRLF,
+                       ),
+                       'Spacing paragraph' => array(
+                               '<p>&nbsp;</p>',
+                               CRLF,
+                       ),
+                       'Double spacing paragraph' => array(
+                               '<p>&nbsp;</p>' . '<p>&nbsp;</p>',
+                               CRLF . CRLF,
+                       ),
+                       'Plain text' => array(
+                               'plain text',
+                               'plain text',
+                       ),
+                       'Plain text followed by linebreak' => array(
+                               'plain text' . CRLF,
+                               'plain text ',
+                       ),
+                       'Paragraph' => array(
+                               '<p>paragraph</p>',
+                               'paragraph',
+                       ),
+                       'Paragraph followed by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . 'paragraph2',
+                       ),
+                       'Double spacing paragraph' => array(
+                               '<p>&nbsp;</p><p>&nbsp;</p><p>paragraph1</p>',
+                               CRLF . CRLF . paragraph1,
+                       ),
+                       'Paragraph followed by linebreak' => array(
+                               '<p>paragraph</p>' . CRLF,
+                               'paragraph',
+                       ),
+                       'Paragraph followed by spacing paragraph' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>',
+                               'paragraph' . CRLF . CRLF,
+                       ),
+                       'Paragraph followed by spacing paragraph, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
+                               'paragraph' . CRLF . CRLF,
+                       ),
+                       'Paragraph followed by double spacing paragraph' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>',
+                               'paragraph' . CRLF . CRLF . CRLF,
+                       ),
+                       'Paragraph followed by double spacing paragraph, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                               'paragraph' . CRLF . CRLF . CRLF,
+                       ),
+                       'Paragraph followed by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by spacing paragraph and by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>&nbsp;</p>' . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by spacing paragraph and by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . CRLF . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                               'paragraph1' . CRLF . CRLF . CRLF . 'paragraph2',
+                       ),
+                       'Paragraph followed by block' => array(
+                               '<p>paragraph</p>' . '<h1>block</h1>',
+                               'paragraph' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                               'paragraph' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by spacing paragraph and block' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<h1>block</h1>',
+                               'paragraph' . CRLF . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by spacing paragraph and block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                               'paragraph' . CRLF . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and block' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<h1>block</h1>',
+                               'paragraph' . CRLF . CRLF . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                               'paragraph' . CRLF . CRLF . CRLF . '<h1>block</h1>',
+                       ),
+                       'Block followed by block' => array(
+                               '<h1>block1</h1>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by empty paragraph and block' => array(
+                               '<h1>block1</h1>' . '<p></p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by empty paragraph aand block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p></p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by spacing paragraph' => array(
+                               '<h1>block1</h1>' . '<p>&nbsp;</p>',
+                               '<h1>block1</h1>' . CRLF . CRLF,
+                       ),
+                       'Block followed by spacing paragraph, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>',
+                               '<h1>block1</h1>' . CRLF . CRLF,
+                       ),
+                       'Block followed by spacing paragraph and block' => array(
+                               '<h1>block1</h1>' . '<p>&nbsp;</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by spacing paragraph and block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by double spacing paragraph and by block' => array(
+                               '<h1>block1</h1>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by double spacing paragraph and by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by paragraph and block' => array(
+                               '<h1>block1</h1>' . '<p>paragraph</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by paragraph and block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by paragraph, spacing paragraph and block' => array(
+                               '<h1>block1</h1>' . '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by paragraph, spacing paragraph and block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . CRLF . '<h1>block2</h1>',
+                       ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider paragraphCorrectlyTransformedOnWayToDatabaseProvider
+        */
+       public function paragraphCorrectlyTransformedOnWayToDatabase($content, $expectedResult) {
+               $thisConfig = array('proc.' => $this->fixture->procOptions);
+               $this->assertEquals($expectedResult, $this->fixture->RTE_transform($content, array(), 'db', $thisConfig));
+       }
+
+       /**
+        * Data provider for lineBreakCorrectlyTransformedOnWayToRte
+        */
+       public static function lineBreakCorrectlyTransformedOnWayToRteProvider() {
+               return array(
+                       'Empty string' => array(
+                               '',
+                               '',
+                       ),
+                       'Single linebreak' => array(
+                               CRLF,
+                               '<p>&nbsp;</p>',
+                       ),
+                       'Double linebreak' => array(
+                               CRLF . CRLF,
+                               '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Triple linebreak' => array(
+                               CRLF . CRLF . CRLF,
+                               '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph' => array(
+                               'paragraph',
+                               '<p>paragraph</p>',
+                       ),
+                       'Paragraph followed by single linebreak' => array(
+                               'paragraph' . CRLF,
+                               '<p>paragraph</p>',
+                       ),
+                       'Paragraph followed by double linebreak' => array(
+                               'paragraph' . CRLF . CRLF,
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph followed by triple linebreak' => array(
+                               'paragraph' . CRLF . CRLF . CRLF,
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph followed by paragraph' => array(
+                               'paragraph1' . CRLF . 'paragraph2',
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by double linebreak and paragraph' => array(
+                               'paragraph1' . CRLF . CRLF . 'paragraph2',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by triple linebreak and paragraph' => array(
+                               'paragraph1' . CRLF . CRLF . CRLF . 'paragraph2',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by block' => array(
+                               'paragraph' . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by linebreak and block' => array(
+                               'paragraph' . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by double linebreak and block' => array(
+                               'paragraph' . CRLF . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by triple linebreak and block' => array(
+                               'paragraph' . CRLF . CRLF . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Block followed by block' => array(
+                               '<h1>block1</h1>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by single linebreak and block' => array(
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by double linebreak and block' => array(
+                               '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by triple linebreak and block' => array(
+                               '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by paragraph and block' => array(
+                               '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider lineBreakCorrectlyTransformedOnWayToRTEProvider
+        */
+       public function lineBreakCorrectlyTransformedOnWayToRTE($content, $expectedResult) {
+               $thisConfig = array('proc.' => $this->fixture->procOptions);
+               $this->assertEquals($expectedResult, $this->fixture->RTE_transform($content, array(), 'rte', $thisConfig));
+       }
+
+       /**
+        * Data provider for paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRte
+        */
+       public static function paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider() {
+               return array(
+                       'Empty string' => array(
+                               '',
+                               '',
+                       ),
+                       'Empty paragraph' => array(
+                               '<p></p>',
+                               '<p>&nbsp;</p>',
+                       ),
+                       'Double empty paragraph' => array(
+                               '<p></p><p></p>',
+                               '<p>&nbsp;</p>'. CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Triple empty paragraph' => array(
+                               '<p></p><p></p><p></p>',
+                               '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Plain text' => array(
+                               'plain text',
+                               '<p>plain text</p>',
+                       ),
+                       'Plain text followed by linebreak' => array(
+                               'plain text' . CRLF,
+                               '<p>plain text </p>',
+                       ),
+                       'Plain text followed by paragraph' => array(
+                               'plain text' . '<p>paragraph</p>',
+                               '<p>plain text</p>' . CRLF . '<p>paragraph</p>',
+                       ),
+                       'Spacing paragraph' => array(
+                               '<p>&nbsp;</p>',
+                               '<p>&nbsp;</p>',
+                       ),
+                       'Double spacing paragraph' => array(
+                               '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                               '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph' => array(
+                               '<p>paragraph</p>',
+                               '<p>paragraph</p>',
+                       ),
+                       'Paragraph followed by linebreak' => array(
+                               '<p>paragraph</p>' . CRLF,
+                               '<p>paragraph</p>',
+                       ),
+                       'Paragraph followed by spacing paragraph' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph followed by double spacing paragraph' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
+                       ),
+                       'Paragraph followed by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by spacing paragraph and by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>&nbsp;</p>' . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by spacing paragraph and by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by paragraph' => array(
+                               '<p>paragraph1</p>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by paragraph, linebreak-separated' => array(
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                               '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
+                       ),
+                       'Paragraph followed by block' => array(
+                               '<p>paragraph</p>' . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by spacing paragraph and by block' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by spacing paragraph and by block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by block' => array(
+                               '<p>paragraph</p>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Paragraph followed by double spacing paragraph and by block, linebreak-separated' => array(
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                               '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
+                       ),
+                       'Block followed by block' => array(
+                               '<h1>block1</h1>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by empty paragraph and by block' => array(
+                               '<h1>block1</h1>' . '<p></p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by empty paragraph and by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p></p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by spacing paragraph and by block' => array(
+                               '<h1>block1</h1>' . '<p>&nbsp;</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by spacing paragraph and by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by double spacing paragraph and by block' => array(
+                               '<h1>block1</h1>' . '<p>&nbsp;</p>' . '<p>&nbsp;</p>' . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+                       'Block followed by double spacing paragraph and by block, linebreak-separated' => array(
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                               '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
+                       ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
+        */
+       public function paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult) {
+               $thisConfig = array('proc.' => $this->fixture->procOptions);
+               $this->assertEquals($expectedResult, $this->fixture->RTE_transform($this->fixture->RTE_transform($content, array(), 'db', $thisConfig), array(), 'rte', $thisConfig));
        }
 }
 ?>
\ No newline at end of file