PEAR logo

PHP_CompatInfo : The Definitive Guide

Detection of a directory

Parsing a full directory, recursively or not, is no more difficult than detect PHP version of a single file.

This new example is based on auto detection of HTML_CSS 1.5.1 distribution. As we will see, basic detection is not accurate as it should be. But with an option we can get the real result (PHP minimum = 4.3.0).

First begin to download the archive from http://pear.php.net/package/HTML_CSS/download/1.5.1 and extract the full contents to a temporary directory (in our example its '/tmp')

We will focus on two important files: CSS.php and CSS/Error.php. So we will indicate to PCI to ignore examples/, and tests/ directories.

Here is the detection script:

  1. <?php
  2. require_once 'PHP/CompatInfo.php';
  3.  
  4. $source  = '/tmp/HTML_CSS-1.5.1';
  5. $options = array('ignore_dirs' => array('examples', 'tests'));
  6.  
  7. $info = new PHP_CompatInfo();
  8. $info->parseDir($source, $options);
  9. // you may also use unified method:  $info->parseData($source, $options);
  10. ?>

And displayed results are :

array (
  'ignored_files' =>
  array (
    0 => '/tmp/HTML_CSS-1.5.1/ChangeLog',
    1 => '/tmp/HTML_CSS-1.5.1/package.xml',
    2 => '/tmp/HTML_CSS-1.5.1/tests/AllTests.php',
    3 => '/tmp/HTML_CSS-1.5.1/tests/HTML_CSS_TestSuite_Bugs.php',
    4 => '/tmp/HTML_CSS-1.5.1/tests/HTML_CSS_TestSuite_Standard.php',
    5 => '/tmp/HTML_CSS-1.5.1/tests/stylesheet.css',
    6 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Advanced.php',
    7 => '/tmp/HTML_CSS-1.5.1/examples/CSS_DisplayOnline.php',
    8 => '/tmp/HTML_CSS-1.5.1/examples/css_errorstack_custom.php',
    9 => '/tmp/HTML_CSS-1.5.1/examples/css_errorstack_logger.php',
    10 => '/tmp/HTML_CSS-1.5.1/examples/css_error_custom.php',
    11 => '/tmp/HTML_CSS-1.5.1/examples/css_error_ignore.php',
    12 => '/tmp/HTML_CSS-1.5.1/examples/css_error_logger.php',
    13 => '/tmp/HTML_CSS-1.5.1/examples/CSS_grepStyles.php',
    14 => '/tmp/HTML_CSS-1.5.1/examples/CSS_InHeader.php',
    15 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Inline.php',
    16 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Logger.php',
    17 => '/tmp/HTML_CSS-1.5.1/examples/CSS_parseData.php',
    18 => '/tmp/HTML_CSS-1.5.1/examples/CSS_req12194_atrule_api.php',
    19 => '/tmp/HTML_CSS-1.5.1/examples/CSS_req12194_atrule_parser.php',
    20 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Stylesheet.php',
    21 => '/tmp/HTML_CSS-1.5.1/examples/CSS_validate.php',
  ),
  'ignored_functions' =>
  array (
  ),
  'ignored_extensions' =>
  array (
  ),
  'ignored_constants' =>
  array (
  ),
  'max_version' => '',
  'version' => '5.0.0',
  'extensions' =>
  array (
    0 => 'date',
    1 => 'pcre',
  ),
  'constants' =>
  array (
  ),
  'tokens' =>
  array (
  ),
  'cond_code' =>
  array (
    0 => 1,
  ),
  '/tmp/HTML_CSS-1.5.1/CSS.php' =>
  array (
    'ignored_functions' =>
    array (
    ),
    'ignored_extensions' =>
    array (
    ),
    'ignored_constants' =>
    array (
    ),
    'max_version' => '',
    'version' => '5.0.0',
    'extensions' =>
    array (
      0 => 'date',
      1 => 'pcre',
    ),
    'constants' =>
    array (
    ),
    'tokens' =>
    array (
    ),
    'cond_code' =>
    array (
      0 => 1,
    ),
  ),
  '/tmp/HTML_CSS-1.5.1/CSS/Error.php' =>
  array (
    'ignored_functions' =>
    array (
    ),
    'ignored_extensions' =>
    array (
    ),
    'ignored_constants' =>
    array (
    ),
    'max_version' => '',
    'version' => '4.3.0',
    'extensions' =>
    array (
      0 => 'date',
    ),
    'constants' =>
    array (
    ),
    'tokens' =>
    array (
    ),
    'cond_code' =>
    array (
      0 => 0,
    ),
  ),
)
    

As we can read, PHP 5.0.0 is required to run the package.

Yes, but its the wrong result. HTML_CSS 1.5.1 require only PHP 4.3.0 to run.

[Tip] Tip

If you have cond_code offset with a value different than zero, you are almost sure that the version given is wrong.

So why we get such result ?

Package PEAR::HTML_CSS 1.5.1 as many application/extension use conditional code to emulate function that are unavailable for previous PHP versions. Its means that HTML_CSS use the php function function_exists() to implement such alternative.

To illustrate our purpose, we can find in source code (CSS.php) :

  1. <?php
  2. // ...
  3.     if (function_exists('file_put_contents')) {
  4.         file_put_contents($filename, $this->toString());
  5.     } else {
  6.         $file = fopen($filename, 'wb');
  7.         fwrite($file, $this->toString());
  8.         fclose($file);
  9.     }
  10. // ...
  11. ?>

PHP function file_put_contents() came with version 5.0.0; That is the reason of wrong parsing result. But we can catch such conditional code.

Let's see now how to set the good accuracy with conditional code analysis.

PHP_CompatInfo : The Definitive Guide v 1.8.0 : August 1, 2008