Uploaded image for project: 'eZ Publish / Platform'
  1. eZ Publish / Platform
  2. EZP-16814

Rendering problems in ezxmltext datatype.

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: High
    • Resolution: Fixed
    • Affects Version/s: 4.3.0
    • Fix Version/s: 4.4.0alpha3
    • Labels:
      None
    • Environment:

      Operating System: Linux ( Ubuntu )
      PHP Version: (please be specific, like '4.4.3' or '5.1.5') 5.2.4-2ubuntu5.9
      Database and version: Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (x86_64) using readline 5.2
      Browser (and version):

      Description

      *The problem*

      After upgrading a couple of sites to version 4.3 we got reports from customers about missing content
      on the sites. After some investigation we discovered that some paragraphs in ezxmltext attributes
      were not visible even if they existed in the database.

      *The cause*

      We traced the problem to the renderParagraph method in the eZXHTMLXMLOutput class.

      This is the method eZXHTMLXMLOutput::renderParagraph in the file kernel/classes/datatypes/ezxmltext/handlers/output/ezxhtmlxmloutput.php

      	
      429:  function renderParagraph( $element, $childrenOutput, $vars )
      430:  {
      431:      // don't render if inside 'li' or inside 'td' (by option)
      432:      $parent = $element->parentNode;
      433:
      434:
      435:      if ( ( $parent->nodeName == 'li' && self::childTagCount( $parent ) == 1 ) ||
      436:           ( $parent->nodeName == 'td' && !$this->RenderParagraphInTableCells && self::childTagCount( $parent ) == 1 ) )
      437:
      438:      {
      439:          return $childrenOutput;
      440:      }
      441:
      442:      // Break paragraph by block tags (like table, ol, ul, header and paragraphs)
      443:      $tagText = '';
      444:      $lastTagInline = null;
      445:      $inlineContent = '';
      446:      foreach( $childrenOutput as $key => $childOutput )
      447:      {
      448:          if ( $childOutput[0] === true )// is inline
      449:          {
      450:              if( $childOutput[1] === ' ' )
      451:              {
      452:                  continue;
      453:              }
      454:
      455:              $inlineContent .= $childOutput[1];
      456:          }
      457:
      458:          // Only render paragraph if current tag is block and previous was an inline tag
      459:          // OR  if current one is inline and it's the last item in the child list
      460:          if ( ( $childOutput[0] === false && $lastTagInline === true ) ||
      461:               ( $childOutput[0] === true && !isset( $childrenOutput[ $key + 1 ]  ) ) )
      462:          {
      463:              $tagText .= $this->renderTag( $element, $inlineContent, $vars );
      464:              $inlineContent = '';
      465:          }
      466:
      467:          if ( $childOutput[0] === false )// is block
      468:              $tagText .= $childOutput[1];
      469:
      470:          $lastTagInline = $childOutput[0];
      471:      }
      472:      return array( false, $tagText );
      473:  }
      
      

      In line 463 the content of the variable $inlineContent will be rendered if current tag is inline
      and it is the last item in the $childrenOutput array. But if the last item in the $childrenOutput
      array is inline and contains a space then $inlinecontent that contains content from previous inline
      tags will not be rendered because the continue statement in line 452 skips the rest of the code in the
      foreach loop including the code that renders the inline content of the last tag.

      *The solution*

      *** 449,455 ****
      --- 449,457 ----
                    {
                        if( $childOutput[1] === ' ' )
                        {
      +                 	if( array_key_exists($key + 1, $childrenOutput) ) {
                            continue;
      +                   }
                        }
        
                        $inlineContent .= $childOutput[1];
      

      We added a check that made sure the continue statement was not called on the last element. That made
      the missing content appear on the websites again.

      Steps to reproduce

      This is not easy to reproduce, but upon request I can provide a database with this problem.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              andre1 André R
              Reporter:
              rv Ronny Vedå
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: