Subversion Repositories PHPX

Rev

Rev 20 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 20 Rev 21
1
<?php
1
<?php
2
2
3
require_once 'global.inc';
3
require_once 'global.inc';
4
4
5
$encoding = mb_detect_encoding(file_get_contents($_SERVER['SCRIPT_FILENAME']));
5
$encoding = mb_detect_encoding(file_get_contents($_SERVER['SCRIPT_FILENAME']));
6
if ($encoding === 'ASCII') $encoding = 'iso-8859-1';
6
if ($encoding === 'ASCII') $encoding = 'iso-8859-1';
7
define('FEATURES_ENCODING', $encoding);
7
define('FEATURES_ENCODING', $encoding);
8
8
9
/**
9
/**
10
 * A list of language features with URNs definitions
10
 * A list of language features with URNs definitions
11
 * for reference links.
11
 * for reference links.
12
 */
12
 */
13
class FeatureList
13
class FeatureList
14
{
14
{
15
  public $versions = array();
15
  public $versions = array();
16
 
16
 
17
  /**
17
  /**
18
   * Versions of implementations that are considered safe.
18
   * Versions of implementations that are considered safe.
19
   * A feature is considered safe if it does not require
19
   * A feature is considered safe if it does not require
20
   * an implementation version above these versions.
20
   * an implementation version above these versions.
21
   *
21
   *
22
   * @var Array[string=>string]
22
   * @var Array[string=>string]
23
   */
23
   */
24
  public $safeVersions = array();
24
  public $safeVersions = array();
25
 
25
 
26
  /**
26
  /**
27
   * URNs that can be used for reference links.
27
   * URNs that can be used for reference links.
28
   *
28
   *
29
   * @var Array[string=>string]
29
   * @var Array[string=>string]
30
   */
30
   */
31
  protected $urns = array();
31
  protected $urns = array();
32
 
32
 
33
  /**
33
  /**
34
   * <code>true</code> generates form controls for submitting test case
34
   * <code>true</code> generates form controls for submitting test case
35
   * results
35
   * results
36
   *
36
   *
37
   * @var bool
37
   * @var bool
38
   */
38
   */
39
  protected $testcase = false;
39
  protected $testcase = false;
40
 
40
 
41
  /**
41
  /**
42
   * The list of language features
42
   * The list of language features
43
   *
43
   *
44
   * @var array[Features]
44
   * @var array[Features]
45
   */
45
   */
46
  protected $items = array();
46
  protected $items = array();
47
 
47
 
48
  /**
48
  /**
49
   * Determines the number of printed items the table headings should be repeated
49
   * Determines the number of printed items the table headings should be repeated
50
   *
50
   *
51
   * @var int
51
   * @var int
52
   */
52
   */
53
  protected $headerRepeat = 25;
53
  protected $headerRepeat = 25;
54
54
55
  /**
55
  /**
56
   * Initializes the FeatureList object
56
   * Initializes the FeatureList object
57
   *
57
   *
58
   * @param array|Object $a
58
   * @param array|Object $a
59
   * @return FeatureList
59
   * @return FeatureList
60
   */
60
   */
61
  public function __construct($a)
61
  public function __construct($a)
62
  {
62
  {
63
    $aVars = get_class_vars(get_class($this));
63
    $aVars = get_class_vars(get_class($this));
64
   
64
   
65
65
66
    foreach ($aVars as $key => $value)
66
    foreach ($aVars as $key => $value)
67
    {
67
    {
68
      if (isset($a[$key]))
68
      if (isset($a[$key]))
69
      {
69
      {
70
        $this->$key = $a[$key];
70
        $this->$key = $a[$key];
71
      }
71
      }
72
    }
72
    }
73
73
74
    /* Inform items of ourself so that URNs can be used for links */
74
    /* Inform items of ourself so that URNs can be used for links */
75
    if (is_array($this->items))
75
    if (is_array($this->items))
76
    {
76
    {
77
      foreach ($this->items as &$item)
77
      foreach ($this->items as &$item)
78
      {
78
      {
79
        $item->setList($this);
79
        $item->setList($this);
80
      }
80
      }
81
    }
81
    }
82
   
82
   
83
    /* resolve URN references that are URNs */
83
    /* resolve URN references that are URNs */
84
    if (is_array($this->urns))
84
    if (is_array($this->urns))
85
    {
85
    {
86
      foreach ($this->urns as &$urn)
86
      foreach ($this->urns as &$urn)
87
      {
87
      {
88
        if (($url = $this->resolveURN($urn)))
88
        if (($url = $this->resolveURN($urn)))
89
        {
89
        {
90
          $urn = $url;
90
          $urn = $url;
91
        }
91
        }
92
      }
92
      }
93
    }
93
    }
94
  }
94
  }
95
 
95
 
96
  /*
96
  /*
97
   * Protected properties may be read, but not written
97
   * Protected properties may be read, but not written
98
   */
98
   */
99
  public function __get($property)
99
  public function __get($property)
100
  {
100
  {
101
    if (property_exists(get_class($this), $property))
101
    if (property_exists(get_class($this), $property))
102
    {
102
    {
103
      return $this->$property;
103
      return $this->$property;
104
    }
104
    }
105
  }
105
  }
106
 
106
 
107
  public function printHeaders()
107
  public function printHeaders()
108
  {
108
  {
109
    foreach ($this->versions as $key => $ver)
109
    foreach ($this->versions as $key => $ver)
110
    {
110
    {
111
      if ($key || $this->testcase)
111
      if ($key || $this->testcase)
112
      {
112
      {
113
?>
113
?>
114
          <th><?php echo $ver; ?></th>
114
          <th><?php echo $ver; ?></th>
115
<?php
115
<?php
116
      }
116
      }
117
    }
117
    }
118
  }
118
  }
119
   
119
   
120
  /**
120
  /**
121
   * Prints the list of features.
121
   * Prints the list of features.
122
   *
122
   *
123
   * @see Feature::printMe()
123
   * @see Feature::printMe()
124
   */
124
   */
125
  public function printItems()
125
  public function printItems()
126
  {
126
  {
127
    $counter = 0;
127
    $counter = 0;
128
    $headerRepeat = $this->headerRepeat;
128
    $headerRepeat = $this->headerRepeat;
129
    $repeatHeaders = ($headerRepeat > 1);
129
    $repeatHeaders = ($headerRepeat > 1);
130
   
130
   
131
    foreach ($this->items as $feature)
131
    foreach ($this->items as $feature)
132
    {
132
    {
133
      if ($feature instanceof Feature)
133
      if ($feature instanceof Feature)
134
      {
134
      {
135
        /*
135
        /*
136
         * TODO: Disabled header repetition until footnote ref. name/ID
136
         * TODO: Disabled header repetition until footnote ref. name/ID
137
         * problem has been solved
137
         * problem has been solved
138
         */
138
         */
139
//        if ($repeatHeaders
139
//        if ($repeatHeaders
140
//            && $counter > 1
140
//            && $counter > 1
141
//            && $counter % $headerRepeat === 0)
141
//            && $counter % $headerRepeat === 0)
142
//        {
142
//        {
143
//          echo <<<HTML
143
//          echo <<<HTML
144
//        <tr class="header">
144
//        <tr class="header">
145
//          <th>Feature</th>
145
//          <th>Feature</th>
146
//          {$this->printHeaders()}
146
//          {$this->printHeaders()}
147
//        </tr>
147
//        </tr>
148
//HTML;
148
//HTML;
149
//        }
149
//        }
150
       
150
       
151
        $feature->printMe();
151
        $feature->printMe();
152
       
152
       
153
        $counter++;
153
        $counter++;
154
      }
154
      }
155
    }
155
    }
156
  }
156
  }
157
 
157
 
158
  /**
158
  /**
159
   * Resolves a URN according to the value of the
159
   * Resolves a URN according to the value of the
160
   * object's <code>$urn</code> property.
160
   * object's <code>$urn</code> property.
161
   *
161
   *
162
   * @param string $urn
162
   * @param string $urn
163
   *   URN to be resolved
163
   *   URN to be resolved
164
   * @return string|boolean
164
   * @return string|boolean
165
   *   The resolved URN if successful,
165
   *   The resolved URN if successful,
166
   *   <code>false</code> otherwise.
166
   *   <code>false</code> otherwise.
167
   */
167
   */
168
  public function resolveURN($urn)
168
  public function resolveURN($urn)
169
  {
169
  {
170
    if (is_array($this->urns))
170
    if (is_array($this->urns))
171
    {
171
    {
172
      $reURN = '|^(.+?):(?!//)|';
172
      $reURN = '|^(.+?):(?!//)|';
173
     
173
     
174
      if (preg_match($reURN, $urn, $m) && isset($this->urns[$m[1]]))
174
      if (preg_match($reURN, $urn, $m) && isset($this->urns[$m[1]]))
175
      {
175
      {
176
        return preg_replace($reURN, $this->urns[$m[1]], $urn);
176
        return preg_replace($reURN, $this->urns[$m[1]], $urn);
177
      }
177
      }
178
    }
178
    }
179
179
180
    return $urn;
180
    return $urn;
181
  }
181
  }
182
}
182
}
183
183
184
/**
184
/**
185
 * A language feature.
185
 * A language feature.
-
 
186
 *
-
 
187
 * @property-read Array[String] $anchors
-
 
188
 *   Fragment identifiers to be defined for quickly accessing
-
 
189
 *   the feature description.
-
 
190
 * @property-read string $title
-
 
191
 *   Value of the explanatory <code>title</code> attribute for the feature.
-
 
192
 * @property-read string $content
-
 
193
 *   Name or example code of the feature
-
 
194
 * @property-read string $descr
-
 
195
 *   Description of the feature.  Displayed directly if code is missing,
-
 
196
 *   otherwise used as `title' attribute value.
-
 
197
 * @property-read Array $versions
-
 
198
 *   Versions that support this feature
-
 
199
 * @property-read List $list
-
 
200
 *   Reference to the FeatureList that this feature belongs to
186
 */
201
 */
187
class Feature
202
class Feature
188
{
203
{
189
  /**
204
  /**
190
   * Fragment identifiers to be defined for quickly accessing
205
   * Fragment identifiers to be defined for quickly accessing
191
   * the feature description.
206
   * the feature description.
192
   *
207
   *
193
   * @var Array[String]
208
   * @var Array[String]
194
   */
209
   */
195
  protected $anchors = array();
210
  protected $anchors = array();
196
 
211
 
197
  /**
212
  /**
198
   * Value of the explanatory <code>title</code> attribute for the feature.
213
   * Value of the explanatory <code>title</code> attribute for the feature.
199
   *
214
   *
200
   * @var string
215
   * @var string
201
   */
216
   */
202
  protected $title = '';
217
  protected $title = '';
203
 
218
 
204
  /**
219
  /**
205
   * Name or example code of the feature
220
   * Name or example code of the feature
206
   *
221
   *
207
   * @var string
222
   * @var string
208
   */
223
   */
209
  protected $content = '';
224
  protected $content = '';
210
   
225
   
211
  /**
226
  /**
212
   * Description of the feature.  Displayed directly if code is missing,
227
   * Description of the feature.  Displayed directly if code is missing,
213
   * otherwise used as `title' attribute value.
228
   * otherwise used as `title' attribute value.
214
   *
229
   *
215
   * @var string
230
   * @var string
216
   */
231
   */
217
  protected $descr = '';
232
  protected $descr = '';
218
 
233
 
219
  /**
234
  /**
220
   * Versions that support this feature
235
   * Versions that support this feature
221
   *
236
   *
222
   * @var Array
237
   * @var Array
223
   */
238
   */
224
  protected $versions = array();
239
  protected $versions = array();
225
   
240
   
226
  /**
241
  /**
227
   * Reference to the FeatureList that this feature belongs to
242
   * Reference to the FeatureList that this feature belongs to
228
   *
243
   *
229
   * @var FeatureList
244
   * @var FeatureList
230
   */
245
   */
231
  protected $list = null;
246
  protected $list = null;
232
 
247
 
233
  public function setList(&$oList)
248
  public function setList(&$oList)
234
  {
249
  {
235
    $this->list =& $oList;
250
    $this->list =& $oList;
236
  }
251
  }
237
252
238
  /**
253
  /**
239
   * Creates a new Feature object, using values from the passed parameters
254
   * Creates a new Feature object, using values from the passed parameters
240
   * array.
255
   * array.
241
   *
256
   *
242
   * @param array|Object $params
257
   * @param array|Object $params
243
   * @return Feature
258
   * @return Feature
244
   */
259
   */
245
  public function __construct($params = array())
260
  public function __construct($params = array())
246
  {
261
  {
247
    $aVars = get_class_vars(__CLASS__);
262
    $aVars = get_class_vars(__CLASS__);
248
   
263
   
249
    foreach ($aVars as $key => $value)
264
    foreach ($aVars as $key => $value)
250
    {
265
    {
251
      if (isset($params[$key]))
266
      if (isset($params[$key]))
252
      {
267
      {
253
        $this->$key = $params[$key];
268
        $this->$key = $params[$key];
254
      }
269
      }
255
    }
270
    }
-
 
271
  }
-
 
272
-
 
273
  /*
-
 
274
  * Protected properties may be read, but not written
-
 
275
  */
-
 
276
  public function __get($property)
-
 
277
  {
-
 
278
    if (property_exists(get_class($this), $property))
-
 
279
    {
-
 
280
      return $this->$property;
-
 
281
    }
256
  }
282
  }
257
 
283
 
258
  /**
284
  /**
259
   * Determines whether one version is greater than another.
285
   * Determines whether one version is greater than another.
260
   *
286
   *
261
   * @param string $v1  Version string #1
287
   * @param string $v1  Version string #1
262
   * @param string $v2  Version string #2
288
   * @param string $v2  Version string #2
263
   * @return bool
289
   * @return bool
264
   *   <code>true</code> if the version <var>$v1</var> is greater than
290
   *   <code>true</code> if the version <var>$v1</var> is greater than
265
   *   the version <var>$v2</var>, <code>false</code> otherwise
291
   *   the version <var>$v2</var>, <code>false</code> otherwise
266
   */
292
   */
267
  protected static function _versionIsGreater($v1, $v2)
293
  protected static function _versionIsGreater($v1, $v2)
268
  {
294
  {
269
    $v1 = explode('.', $v1);
295
    $v1 = explode('.', $v1);
270
    $v2 = explode('.', $v2);
296
    $v2 = explode('.', $v2);
271
   
297
   
272
    foreach ($v1 as $key => $value)
298
    foreach ($v1 as $key => $value)
273
    {
299
    {
274
      if ((int)$value <= (int)$v2[$key])
300
      if ((int)$value <= (int)$v2[$key])
275
      {
301
      {
276
        return false;
302
        return false;
277
      }
303
      }
278
    }
304
    }
279
   
305
   
280
    return true;
306
    return true;
281
  }
307
  }
282
 
308
 
283
  /**
309
  /**
284
   * Returns <code>' class="safe"'</code> if the feature
310
   * Returns <code>' class="safe"'</code> if the feature
285
   * can be considered safe.  The required information
311
   * can be considered safe.  The required information
286
   * is stored in the <code>safeVersions</code> property
312
   * is stored in the <code>safeVersions</code> property
287
   * of the associated <code>FeatureList</code> object.
313
   * of the associated <code>FeatureList</code> object.
288
   *
314
   *
289
   * @return string
315
   * @return string
290
   * @see FeatureList::defaultSafeVersions
316
   * @see FeatureList::defaultSafeVersions
291
   */
317
   */
292
  protected function getSafeStr()
318
  protected function getSafeStr()
293
  {
319
  {
294
    if (!is_null($this->list))
320
    if (!is_null($this->list))
295
    {
321
    {
296
      foreach ($this->list->safeVersions as $impl => &$safeVer)
322
      foreach ($this->list->safeVersions as $impl => &$safeVer)
297
      {
323
      {
298
        $thisImplVer =& $this->versions[$impl];
324
        $thisImplVer =& $this->versions[$impl];
299
        if (is_array($thisImplVer))
325
        if (is_array($thisImplVer))
300
        {
326
        {
301
          if (isset($thisImplVer['tested']) && !is_bool($thisImplVer['tested']))
327
          if (isset($thisImplVer['tested']) && !is_bool($thisImplVer['tested']))
302
          {
328
          {
303
            $thisImplVer =& $thisImplVer['tested'];
329
            $thisImplVer =& $thisImplVer['tested'];
304
          }
330
          }
305
          else
331
          else
306
        {
332
        {
307
            $thisImplVer =& $thisImplVer[0];
333
            $thisImplVer =& $thisImplVer[0];
308
          }
334
          }
309
        }
335
        }
310
       
336
       
311
        /* DEBUG */
337
        /* DEBUG */
312
        // echo " $impl=$thisImplVer ";
338
        // echo " $impl=$thisImplVer ";
313
       
339
       
314
        if (preg_match('/^-?$/', $thisImplVer) || self::_versionIsGreater($thisImplVer, $safeVer))
340
        if (preg_match('/^-?$/', $thisImplVer) || self::_versionIsGreater($thisImplVer, $safeVer))
315
        {
341
        {
316
          return '';
342
          return '';
317
        }
343
        }
318
      }
344
      }
319
     
345
     
320
      return ' class="safe"';
346
      return ' class="safe"';
321
    }
347
    }
322
    else
348
    else
323
    {
349
    {
324
      return '';
350
      return '';
325
    }
351
    }
326
  }
352
  }
327
 
353
 
328
  protected function getTitleStr()
354
  protected function getTitleStr()
329
  {
355
  {
330
    if (!empty($this->title))
356
    if (!empty($this->title))
331
    {
357
    {
332
      return " title=\"{$this->title}\"";
358
      return " title=\"{$this->title}\"";
333
    }
359
    }
334
    else
360
    else
335
    {
361
    {
336
      return '';
362
      return '';
337
    }
363
    }
338
  }
364
  }
339
 
365
 
340
  protected function getAnchors()
366
  protected function getAnchors()
341
  {
367
  {
342
    $result = array();
368
    $result = array();
343
 
369
 
344
    foreach ($this->anchors as $anchor)
370
    foreach ($this->anchors as $anchor)
345
    {
371
    {
346
      $result[] = "<a name=\"{$anchor}\"";
372
      $result[] = "<a name=\"{$anchor}\"";
347
     
373
     
348
      if (preg_match('/^[a-z][a-z0-9_:.-]*/i', $anchor))
374
      if (preg_match('/^[a-z][a-z0-9_:.-]*/i', $anchor))
349
      {
375
      {
350
        $result[] = " id=\"{$anchor}\"";
376
        $result[] = " id=\"{$anchor}\"";
351
      }
377
      }
352
     
378
     
353
      $result[] = '></a>';
379
      $result[] = '></a>';
354
    }
380
    }
355
   
381
   
356
    return join('', $result);
382
    return join('', $result);
357
  }
383
  }
358
384
359
  protected function getAssumed($v)
385
  protected function getAssumed($v)
360
  {
386
  {
361
    if (is_array($v) && isset($v['assumed']) && $v['assumed'])
387
    if (is_array($v) && isset($v['assumed']) && $v['assumed'])
362
    {
388
    {
363
      return ' class="assumed"';
389
      return ' class="assumed"';
364
    }
390
    }
365
   
391
   
366
    return '';
392
    return '';
367
  }
393
  }
368
394
369
  protected function getTested($v)
395
  protected function getTested($v)
370
  {
396
  {
371
    if (is_array($v) && isset($v['tested']) && $v['tested'])
397
    if (is_array($v) && isset($v['tested']) && $v['tested'])
372
    {
398
    {
373
      return ' class="tested"';
399
      return ' class="tested"';
374
    }
400
    }
375
   
401
   
376
    return '';
402
    return '';
377
  }
403
  }
378
 
404
 
379
  /**
405
  /**
380
   * Returns the version of a feature.
406
   * Returns the version of a feature.
381
   *
407
   *
382
   * @param string|VersionInfo $vInfo
408
   * @param string|VersionInfo $vInfo
383
   * @return mixed
409
   * @return mixed
384
   */
410
   */
385
  protected function getVer($vInfo)
411
  protected function getVer($vInfo)
386
  {
412
  {
387
    if (is_array($vInfo))
413
    if (is_array($vInfo))
388
    {
414
    {
389
      /* TODO: Return all versions: documented, assumed, and tested */
415
      /* TODO: Return all versions: documented, assumed, and tested */
390
      $vNumber = (isset($vInfo['tested'])
416
      $vNumber = (isset($vInfo['tested'])
391
                  && gettype($vInfo['tested']) !== 'boolean')
417
                  && gettype($vInfo['tested']) !== 'boolean')
392
                     ? $vInfo['tested']
418
                     ? $vInfo['tested']
393
                     : $vInfo[0];
419
                     : $vInfo[0];
394
      $section = isset($vInfo['section'])
420
      $section = isset($vInfo['section'])
395
                   ? ' <span class="section" title="Specification section">['
421
                   ? ' <span class="section" title="Specification section">['
396
                      . $vInfo['section'] . ']</span>'
422
                      . $vInfo['section'] . ']</span>'
397
                   : '';
423
                   : '';
398
     
424
     
399
      if (isset($vInfo['urn']))
425
      if (isset($vInfo['urn']))
400
      {
426
      {
401
        if ($this->list instanceof FeatureList)
427
        if ($this->list instanceof FeatureList)
402
        {
428
        {
403
          $url = $this->list->resolveURN($vInfo['urn']);
429
          $url = $this->list->resolveURN($vInfo['urn']);
404
          $vNumber = '<a href="' . $url . '">' . $vNumber
430
          $vNumber = '<a href="' . $url . '">' . $vNumber
405
            . ($section ? $section : '') . '</a>';
431
            . ($section ? $section : '') . '</a>';
406
        }
432
        }
407
      }
433
      }
408
      else if ($section)
434
      else if ($section)
409
      {
435
      {
410
        $vNumber .= $section;
436
        $vNumber .= $section;
411
      }
437
      }
412
438
413
      $vInfo = $vNumber;
439
      $vInfo = $vNumber;
414
    }
440
    }
415
441
416
    return ($vInfo === '-')
442
    return ($vInfo === '-')
417
      ? '<span title="Not supported">&#8722;</span>'
443
      ? '<span title="Not supported">&#8722;</span>'
418
      : $vInfo;
444
      : $vInfo;
419
  }
445
  }
420
 
446
 
421
  /**
447
  /**
422
   * Returns a syntax-highlighted version of a string
448
   * Returns a syntax-highlighted version of a string
423
   *
449
   *
424
   * @param string $s
450
   * @param string $s
425
   * @return string
451
   * @return string
426
   */
452
   */
427
  protected static function shl($s)
453
  protected static function shl($s)
428
  {
454
  {
429
    /* stub */
455
    /* stub */
430
    return $s;
456
    return $s;
431
  }
457
  }
432
 
458
 
433
  public function printMe()
459
  public function printMe()
434
  {
460
  {
435
    ?>
461
    ?>
436
<tr<?php echo $this->getSafeStr(); ?>>
462
<tr<?php echo $this->getSafeStr(); ?>>
437
          <th<?php echo $this->getTitleStr(); ?>><?php
463
          <th<?php echo $this->getTitleStr(); ?>><?php
438
            echo $this->getAnchors();
464
            echo $this->getAnchors();
439
            echo /*preg_replace_callback(
465
            echo /*preg_replace_callback(
440
              '#(<code>)(.+?)(</code>)#',
466
              '#(<code>)(.+?)(</code>)#',
441
              array('self', 'shl'),*/
467
              array('self', 'shl'),*/
442
              preg_replace('/&hellip;/', '&#8230;', $this->content)/*)*/;
468
              preg_replace('/&hellip;/', '&#8230;', $this->content)/*)*/;
443
            ?></th>
469
            ?></th>
444
<?php
470
<?php
445
    $versions = $this->versions;
471
    $versions = $this->versions;
446
    $testcase = false;
472
    $testcase = false;
447
    if (!is_null($this->list))
473
    if (!is_null($this->list))
448
    {
474
    {
449
      $versions =& $this->list->versions;
475
      $versions =& $this->list->versions;
450
      $testcase = $this->list->testcase;
476
      $testcase = $this->list->testcase;
451
    }
477
    }
452
478
453
    static $row = 0;
479
    static $row = 0;
454
    $row++;
480
    $row++;
455
   
481
   
456
    $column = 0;
482
    $column = 0;
457
    $thisVersions =& $this->versions;
483
    $thisVersions =& $this->versions;
458
   
484
   
459
    foreach ($versions as $key => $value)
485
    foreach ($versions as $key => $value)
460
    {
486
    {
461
      $column++;
487
      $column++;
462
      $id = "td$row-$column";
488
      $id = "td$row-$column";
463
      $ver = isset($thisVersions[$key]) ? $thisVersions[$key] : '';
489
      $ver = isset($thisVersions[$key]) ? $thisVersions[$key] : '';
464
      if ($key || $testcase)
490
      if ($key || $testcase)
465
      {
491
      {
466
?>
492
?>
467
          <td<?php
493
          <td<?php
468
            if (!$key)
494
            if (!$key)
469
            {
495
            {
470
              echo " id='$id'";
496
              echo " id='$id'";
471
            }
497
            }
472
           
498
           
473
            echo $this->getAssumed($ver) . $this->getTested($ver);
499
            echo $this->getAssumed($ver) . $this->getTested($ver);
474
           
500
           
475
            if (!$key)
501
            if (!$key)
476
            {
502
            {
477
              if (!empty($ver))
503
              if (!empty($ver))
478
              {
504
              {
479
                echo ' title="Test code: '
505
                echo ' title="Test code: '
480
                  . htmlspecialchars(
506
                  . htmlspecialchars(
481
                      preg_replace('/\\\(["\'])/', '\1',
507
                      preg_replace('/\\\(["\'])/', '\1',
482
                        reduceWhitespace($ver)
508
                        reduceWhitespace($ver)
483
                      ),
509
                      ),
484
                      ENT_COMPAT,
510
                      ENT_COMPAT,
485
                      FEATURES_ENCODING
511
                      FEATURES_ENCODING
486
                    )
512
                    )
487
                  . '"';
513
                  . '"';
488
              }
514
              }
489
              else
515
              else
490
            {
516
            {
491
                echo ' title="Not applicable: No automated test case'
517
                echo ' title="Not applicable: No automated test case'
492
                  . ' is available for this feature.  If possible, please'
518
                  . ' is available for this feature.  If possible, please'
493
                  . ' click the feature code in the first column to run'
519
                  . ' click the feature code in the first column to run'
494
                  . ' a manual test."';
520
                  . ' a manual test."';
495
              }
521
              }
496
            }
522
            }
497
            else
523
            else
498
          {
524
          {
499
              echo ' title="'
525
              echo ' title="'
500
                . htmlspecialchars(
526
                . htmlspecialchars(
501
                    preg_replace('/<.*?>/', '', $value),
527
                    preg_replace('/<.*?>/', '', $value),
502
                    ENT_COMPAT, FEATURES_ENCODING)
528
                    ENT_COMPAT, FEATURES_ENCODING)
503
                . '"';
529
                . '"';
504
            }
530
            }
505
            ?>><?php
531
            ?>><?php
506
            if ($key)
532
            if ($key)
507
            {
533
            {
508
              echo $this->getVer($ver);
534
              echo $this->getVer($ver);
509
             
535
             
510
              /* General footnotes support: include footnotes.class.php to enable */
536
              /* General footnotes support: include footnotes.class.php to enable */
511
              if (is_array($ver) && isset($ver['footnote']) && $ver['footnote'])
537
              if (is_array($ver) && isset($ver['footnote']) && $ver['footnote'])
512
              {
538
              {
513
                echo $ver['footnote'];
539
                echo $ver['footnote'];
514
              }
540
              }
515
            }
541
            }
516
            else
542
            else
517
          {
543
          {
518
              if (!empty($ver) && $testcase)
544
              if (!empty($ver) && $testcase)
519
              {
545
              {
520
                ?><script type="text/javascript">
546
                ?><script type="text/javascript">
521
  // <![CDATA[
547
  // <![CDATA[
522
  var s = test(<?php echo $ver; ?>,
548
  var s = test(<?php echo $ver; ?>,
523
    '<input title="Supported" name="<?php echo htmlspecialchars($this->title, ENT_COMPAT, FEATURES_ENCODING); ?>" value="+" readonly>',
549
    '<input title="Supported" name="<?php echo htmlspecialchars($this->title, ENT_COMPAT, FEATURES_ENCODING); ?>" value="+" readonly>',
524
    '<input title="Not supported" name="<?php echo htmlspecialchars($this->title, ENT_COMPAT, FEATURES_ENCODING); ?>" value="&#8722;" readonly>');
550
    '<input title="Not supported" name="<?php echo htmlspecialchars($this->title, ENT_COMPAT, FEATURES_ENCODING); ?>" value="&#8722;" readonly>');
525
  jsx.tryThis("document.write(s);",
551
  jsx.tryThis("document.write(s);",
526
          "document.getElementById('<?php echo $id; ?>').appendChild("
552
          "document.getElementById('<?php echo $id; ?>').appendChild("
527
          + "document.createTextNode(s));");
553
          + "document.createTextNode(s));");
528
  // ]]>
554
  // ]]>
529
</script><?php
555
</script><?php
530
              }
556
              }
531
              else
557
              else
532
            {
558
            {
533
                echo '<abbr>N/A</abbr>';
559
                echo '<abbr>N/A</abbr>';
534
              }
560
              }
535
            }
561
            }
536
            ?></td>
562
            ?></td>
537
<?php
563
<?php
538
      }
564
      }
539
    }
565
    }
540
?>
566
?>
541
        </tr>
567
        </tr>
542
<?php
568
<?php
543
  }
569
  }
544
}
570
}
545
 
571
 
546
?>
572
?>
547
 
573