1

I have been trying to display graphs to users in my Drupal 7 website, by using the PHP library pChart (which comes with a lot of documentation also). Using the libraries module, I have successfully enabled the pChart library.

Then I tried a basic example that came with the downloaded pChart library. Below is the code that I added in a node with the PHP filter enabled,

<?php
$name = "pChart2.1.3";
if ($path = libraries_get_path($name)) {
include($path.'/class/pData.class.php');
include($path.'/class/pDraw.class.php');
include($path.'/class/pImage.class.php');
}
/* Create your dataset object */
$myData = new pData();

/* Add data in your dataset */
$myData->addPoints(array(1,3,4,3,5));

/* Create a pChart object and associate your dataset */
$myPicture = new pImage(700,230,$myData);

/* Choose a nice font */
$myPicture->setFontProperties(array("FontName"=>$path.'/fonts/Forgotte.ttf',"FontSize"=>11));

/* Define the boundaries of the graph area */
$myPicture->setGraphArea(60,40,670,190);

/* Draw the scale, keep everything automatic */
$myPicture->drawScale();

/* Draw the scale, keep everything automatic */
$myPicture->drawSplineChart();

/* Render the picture (choose the best way) */
$myPicture->autoOutput("pictures/example.basic.png");
?>

However, with no errors, warnings or notices, I only get the below unusual output:

screenshot

My Question: So what is this and what am I doing wrong?

1 Answer 1

2

The output you are seeing is simply the PNG file that is being outputs it would be a text file. That is because Drupal already sets the "Content-type" header to "text/html; charset=utf-8," while the method you are calling is setting it to "image/png."

   function stroke($BrowserExpire=FALSE)
    {
     if ( $this->TransparentBackground ) {imagealphablending($this->Picture,false); imagesavealpha($this->Picture,true); }

     if ( $BrowserExpire )
      {
       header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
       header("Cache-Control: no-cache");
       header("Pragma: no-cache");
      }

     header('Content-type: image/png');
     imagepng($this->Picture);
    }

   /* Automatic output method based on the calling interface */
   function autoOutput($FileName="output.png")
    {
     if (php_sapi_name() == "cli")
      $this->Render($FileName);
     else
      $this->Stroke();
    }

What you could do is:

  • Use pChart to create a file containing the chart you want to show
  • Output a <img> tag that references the created file

If imagepng() used the PHP stream wrappers (which is true for file_get_contents()), the following code would work.

/* Render the picture (choose the best way) */
$uri = file_create_filename('example.basic.png', file_build_uri('pictures'));
$myPicture->Render($uri);
echo('<img src="' . file_create_url($uri) . '" />');

In this case, the code is slightly more complex.

/* Render the picture (choose the best way) */
$uri = file_create_filename('example.basic.png', file_build_uri('pictures'));
$instance = file_stream_wrapper_get_instance_by_uri($uri);
if ($filename = $instance->realpath()) {
  $myPicture->Render($filename);
  echo('<img src="' . file_create_url($uri) . '" />');
}

I wrote a conditional statement around $filename = $instance->realpath() because DrupalLocalStreamWrapper::getLocalPath(), the method called by DrupalLocalStreamWrapper::realpath(), can return FALSE when it cannot determinate the real path.

file_create_filename() is a function that returns a unique filename; in the case there is already a file with the name passed as argument, the function adds a number at the end of the filename, checking every time the file doesn't exist already. If "example.basic.png" is the name of an existing file, the function will try with "example.basic_0.png"; if there is already a file using that filename, it will try with "example.basic_1.png"; the loop is continued until the function find a filename that is not already used.

In the case you need to the filename to a function, as in this case, try first the file_create_filename($filename, file_build_uri($directory)) approach, when you are not sure the function to which you are passing the filename is using PHP stream wrappers; only in the case it doesn't, you should use file_stream_wrapper_get_instance_by_uri() as in the second snippet.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.