Subversion Repositories PHPX

Rev

Rev 79 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7 PointedEar 1
<?php
2
 
3
/**
80 PointedEar 4
 * A footnote list contains {@link Footnote Footnotes}
7 PointedEar 5
 *
6
 * @author Thomas 'PointedEars' Lahn &lt;php@PointedEars.de&gt;
7
 */
8
class FootnoteList
9
{
10
  /**
11
   * The footnotes of this list
12
   *
13
   * @var Array
14
   */
25 PointedEar 15
  protected $_footnotes;
80 PointedEar 16
 
7 PointedEar 17
  /**
18
   * Last used number sign for a footnote
19
   *
20
   * @var int
21
   */
25 PointedEar 22
  protected $_lastNumberSign;
80 PointedEar 23
 
25 PointedEar 24
  protected $_defaultPrefix;
25
  protected $_defaultSuffix;
80 PointedEar 26
 
25 PointedEar 27
  protected $_makeTooltip;
79 PointedEar 28
 
29
  /* (non-PHPdoc) @see Footnote::_html4Compat */
30
  protected $_html4Compat;
80 PointedEar 31
 
79 PointedEar 32
  public function __construct($defaultPrefix = '', $defaultSuffix = '', $makeTooltip = false, $html4Compatible = false)
7 PointedEar 33
  {
34
    $this->clear();
25 PointedEar 35
    $this->_defaultPrefix = $defaultPrefix;
36
    $this->_defaultSuffix = $defaultSuffix;
37
    $this->_makeTooltip = $makeTooltip;
79 PointedEar 38
    $this->_html4Compat = $html4Compatible;
7 PointedEar 39
  }
80 PointedEar 40
 
25 PointedEar 41
  public function __get($name)
42
  {
43
    if (property_exists($this, "_$name"))
44
    {
45
      return $this->{"_$name"};
46
    }
47
 
48
    throw new InvalidArgumentException(
49
      'No such property ' . get_class($this) . "::\$$name");
50
  }
80 PointedEar 51
 
7 PointedEar 52
  /**
53
   * Clears the footnote list
54
   */
55
  public function clear()
56
  {
25 PointedEar 57
    $this->_footnotes = array();
58
    $this->_lastNumberSign = 0;
7 PointedEar 59
  }
80 PointedEar 60
 
7 PointedEar 61
  /**
62
   * Adds a footnote to the list (unless already specified)
63
   *
64
   * @param string $name
65
   *   Name of the footnote
66
   * @param string $sign
67
   *   Sign of the footnote.  If empty, the next available number is used.
68
   * @param string $text
69
   *   Text for the footnote
79 PointedEar 70
   * @param string $tooltip
71
   *   Tooltip for the footnote
7 PointedEar 72
   * @return string
73
   *   The code for printing the footnote reference.
74
   */
13 PointedEar 75
  public function add($name, $sign = '', $text = '', $tooltip = null)
7 PointedEar 76
  {
25 PointedEar 77
    $footnotes =& $this->_footnotes;
80 PointedEar 78
 
7 PointedEar 79
    if (!isset($footnotes[$name]))
80
    {
81
      if (!$sign)
82
      {
25 PointedEar 83
        $sign = ++$this->_lastNumberSign;
7 PointedEar 84
      }
11 PointedEar 85
      else if (is_int($sign))
86
      {
25 PointedEar 87
        $this->_lastNumberSign = $sign;
11 PointedEar 88
      }
80 PointedEar 89
 
13 PointedEar 90
      $footnotes[$name] = new Footnote($name, $sign, $text,
25 PointedEar 91
        $this->_defaultSuffix, $this->_defaultPrefix,
79 PointedEar 92
        $this->_makeTooltip ? ($tooltip !== null ? $tooltip : $text) : '',
93
        $this->_html4Compat);
7 PointedEar 94
    }
80 PointedEar 95
 
8 PointedEar 96
    return $footnotes[$name]->getRef();
7 PointedEar 97
  }
80 PointedEar 98
 
7 PointedEar 99
  /**
100
   * Prints the list of footnotes
101
   */
102
  public function printMe()
103
  {
25 PointedEar 104
    $footnotes =& $this->_footnotes;
80 PointedEar 105
 
25 PointedEar 106
    uasort($footnotes, function ($a, $b) {
107
      /* Sort numbered footnotes first */
108
      if (is_int($a->sign) && !is_int($b->sign))
8 PointedEar 109
      {
110
        return -1;
111
      }
25 PointedEar 112
 
113
      if (is_int($b->sign) && !is_int($a->sign))
8 PointedEar 114
      {
115
        return 1;
116
      }
80 PointedEar 117
 
25 PointedEar 118
      /* Sort footnotes either numerically or alphabetically */
119
      /* TODO: Sort "1b" before "12a" */
120
      if ($a->sign < $b->sign)
8 PointedEar 121
      {
25 PointedEar 122
        return -1;
8 PointedEar 123
      }
80 PointedEar 124
 
25 PointedEar 125
      if ($a->sign > $b->sign)
126
      {
127
        return 1;
128
      }
80 PointedEar 129
 
25 PointedEar 130
      return 0;
131
    });
80 PointedEar 132
 
8 PointedEar 133
    ?><table class="footnotes">
134
    <?php
80 PointedEar 135
 
7 PointedEar 136
    foreach ($footnotes as $name => &$footnote)
137
    {
138
      $footnote->printMe();
139
    }
80 PointedEar 140
 
8 PointedEar 141
    ?></table><?php
7 PointedEar 142
  }
80 PointedEar 143
 
7 PointedEar 144
  /**
145
   * Prints the list of footnotes and clears the list in memory
146
   */
147
  public function flush()
148
  {
149
    $this->printMe();
150
    $this->clear();
151
  }
152
}
153
 
154
/**
80 PointedEar 155
 * A footnote to be used in a {@link FootnoteList "footnote list"}
7 PointedEar 156
 *
157
 * @author Thomas 'PointedEars' Lahn &lt;php@PointedEars.de&gt;
158
 */
159
class Footnote
160
{
161
  /**
8 PointedEar 162
   * The name of this footnote
163
   *
164
   * @var string
165
   */
25 PointedEar 166
  protected $_name = '';
80 PointedEar 167
 
8 PointedEar 168
  /**
7 PointedEar 169
   * The sign used for referring to this footnote
170
   *
171
   * @var string
172
   */
25 PointedEar 173
  protected $_sign = '';
80 PointedEar 174
 
7 PointedEar 175
  /**
176
   * The text for this footnote
177
   *
178
   * @var string
179
   */
25 PointedEar 180
  protected $_text = '';
80 PointedEar 181
 
25 PointedEar 182
  protected $_prefix = '';
183
  protected $_suffix = '';
184
  protected $_tooltip = '';
79 PointedEar 185
 
186
  /**
187
   * HTML 4 compatibility: If <code>true</code>, generates
188
   * <code>name</code> attributes.  Default: <code>false</code>.
189
   *
190
   * @var boolean
191
   */
192
  protected $_html4Compat = false;
80 PointedEar 193
 
7 PointedEar 194
  /**
8 PointedEar 195
   * The number of times this footnote has been referred
196
   *
197
   * @var int
198
   */
25 PointedEar 199
  protected $_references = 0;
80 PointedEar 200
 
8 PointedEar 201
  /**
7 PointedEar 202
   * Creates a footnote
203
   *
8 PointedEar 204
   * @param string $name
205
   *   The name of this footnote
7 PointedEar 206
   * @param string $sign
207
   *   The sign that should be used for referring to this footnote
208
   * @param string $text
209
   *   The text for this footnote
13 PointedEar 210
   * @param string $suffix
211
   *   The suffix for this footnote
212
   * @param string $prefix
213
   *   The prefix for this footnote
7 PointedEar 214
   */
13 PointedEar 215
  public function __construct($name, $sign, $text, $suffix = '', $prefix = '',
79 PointedEar 216
                                 $tooltip = '', $html4Compatible = false)
7 PointedEar 217
  {
25 PointedEar 218
    $this->_name = $name;
219
    $this->_sign = (is_numeric($sign) ? (int) $sign : $sign);
220
    $this->_text = $text;
221
    $this->_suffix = $suffix;
222
    $this->_prefix = $prefix;
223
    $this->_tooltip = $tooltip;
79 PointedEar 224
    $this->_html4Compat = $html4Compatible;
7 PointedEar 225
  }
8 PointedEar 226
 
227
  /**
228
   * Universal getter
229
   *
230
   * @param string $name
231
   *   Name of the property to be read-accessed.  Currently only 'sign'
232
   *   is supported.
10 PointedEar 233
   * @throws InvalidArgumentException if a non-existing property is accessed
8 PointedEar 234
   * @return mixed
235
   *   Property value
236
   */
237
  public function __get($name)
238
  {
25 PointedEar 239
    if (property_exists($this, "_$name"))
8 PointedEar 240
    {
25 PointedEar 241
      return $this->{"_$name"};
8 PointedEar 242
    }
25 PointedEar 243
 
244
    throw new InvalidArgumentException(
245
      'No such property ' . get_class($this) . "::\$$name");
8 PointedEar 246
  }
80 PointedEar 247
 
7 PointedEar 248
  /**
249
   * Returns the reference for this footnote
250
   *
251
   * @return string
252
   */
8 PointedEar 253
  public function getRef()
7 PointedEar 254
  {
25 PointedEar 255
    $s = $this->_name;
79 PointedEar 256
 
8 PointedEar 257
    $ret = "<sup><a href='#footnote-{$s}'"
25 PointedEar 258
      . ($this->_references === 0
79 PointedEar 259
        ? (($this->_html4Compat ? " name='fn-{$s}-ref'" : "") . " id='fn-{$s}-ref'")
8 PointedEar 260
        : '')
15 PointedEar 261
      . ' class="footnote"'
25 PointedEar 262
      . ($this->_tooltip
13 PointedEar 263
        ? ' title="'
264
          . preg_replace('/"/', '&quot;',
25 PointedEar 265
              trim(reduceWhitespace(strip_tags($this->_tooltip))))
13 PointedEar 266
          . '"'
267
        : '')
25 PointedEar 268
      . ">{$this->_prefix}{$this->_sign}{$this->_suffix}"
13 PointedEar 269
      . '</a></sup>';
8 PointedEar 270
 
25 PointedEar 271
    ++$this->_references;
80 PointedEar 272
 
8 PointedEar 273
    return $ret;
7 PointedEar 274
  }
80 PointedEar 275
 
7 PointedEar 276
  /**
277
   * Prints this footnote in a footnote list
278
   */
279
  public function printMe()
280
  {
25 PointedEar 281
    $s = $this->_name;
80 PointedEar 282
 
8 PointedEar 283
    echo "  <tr>
79 PointedEar 284
        <th><sup><a" . ($this->_html4Compat ? " name='footnote-{$s}'" : "")
285
      . " id='footnote-{$s}' class='footnote'
25 PointedEar 286
          >{$this->_sign}</a></sup><a
16 PointedEar 287
          href='#fn-{$s}-ref' class='backref'>&#8593;</a></th>
25 PointedEar 288
        <td>{$this->_text}</td>
8 PointedEar 289
      </tr>
290
    ";
7 PointedEar 291
  }
292
}
293
 
79 PointedEar 294
?>