Subversion Repositories PHPX

Rev

Rev 16 | Rev 79 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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