1<?php 2 3/** 4 * Plugin RefNotes: Note 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Mykola Ostrovskyy <dwpforge@gmail.com> 8 */ 9 10//////////////////////////////////////////////////////////////////////////////////////////////////// 11class refnotes_note_block_iterator extends FilterIterator { 12 13 private $note; 14 private $limit; 15 private $count; 16 17 /** 18 * Constructor 19 */ 20 public function __construct($note, $limit) { 21 $this->note = new ArrayObject($note); 22 $this->limit = $this->getBlockLimit($limit); 23 $this->count = 0; 24 25 parent::__construct($this->note->getIterator()); 26 } 27 28 /** 29 * 30 */ 31 function accept() { 32 $result = $this->current()->isValid(); 33 34 if ($result) { 35 ++$this->count; 36 } 37 38 return $result; 39 } 40 41 /** 42 * 43 */ 44 function valid() { 45 return parent::valid() && (($this->limit == 0) || ($this->count <= $this->limit)); 46 } 47 48 /** 49 * 50 */ 51 private function getBlockLimit($limit) { 52 if (preg_match('/(\/?)(\d+)/', $limit, $match) == 1) { 53 if ($match[1] != '') { 54 $devider = intval($match[2]); 55 $result = ceil($this->getValidCount() / $devider); 56 } 57 else { 58 $result = intval($match[2]); 59 } 60 } 61 else { 62 $result = 0; 63 } 64 65 return $result; 66 } 67 68 /** 69 * 70 */ 71 private function getValidCount() { 72 $result = 0; 73 74 foreach ($this->note as $note) { 75 if ($note->isValid()) { 76 ++$result; 77 } 78 } 79 80 return $result; 81 } 82} 83 84//////////////////////////////////////////////////////////////////////////////////////////////////// 85class refnotes_note_mock { 86 87 /** 88 * 89 */ 90 public function getScope() { 91 return new refnotes_scope_mock(); 92 } 93 94 /** 95 * 96 */ 97 public function setText($text) { 98 } 99 100 /** 101 * 102 */ 103 public function addReference($reference) { 104 } 105} 106 107//////////////////////////////////////////////////////////////////////////////////////////////////// 108class refnotes_note extends refnotes_refnote { 109 110 protected $scope; 111 protected $namespaceName; 112 protected $id; 113 protected $name; 114 protected $inline; 115 protected $reference; 116 protected $text; 117 protected $processed; 118 119 /** 120 * 121 */ 122 public static function getNamePattern($type) { 123 if (($type == 'full-extended') || ($type == 'extended')) { 124 $result = ($type == 'full-extended') ? refnotes_namespace::getNamePattern('optional') : ''; 125 $result .= '[[:alpha:]\d][\w.&\(\)\[\]{}+-]*'; 126 } 127 else { 128 $result = '[[:alpha:]]\w*'; 129 } 130 131 return $result; 132 } 133 134 /** 135 * Constructor 136 */ 137 public function __construct($scope, $namespaceName, $name) { 138 parent::__construct(); 139 140 $this->scope = $scope; 141 $this->namespaceName = $namespaceName; 142 $this->id = -1; 143 $this->name = $name; 144 $this->inline = false; 145 $this->reference = array(); 146 $this->text = ''; 147 $this->processed = false; 148 } 149 150 /** 151 * 152 */ 153 private function initId() { 154 $this->id = $this->scope->getNoteId(); 155 156 if ($this->name == '') { 157 $this->name = '#' . $this->id; 158 } 159 } 160 161 /** 162 * 163 */ 164 public function getId() { 165 return $this->id; 166 } 167 168 /** 169 * 170 */ 171 public function getName() { 172 return $this->name; 173 } 174 175 /** 176 * 177 */ 178 public function getNamespaceName() { 179 return $this->namespaceName; 180 } 181 182 /** 183 * 184 */ 185 public function getScope() { 186 return $this->scope; 187 } 188 189 /** 190 * 191 */ 192 public function setText($text) { 193 if ($this->text == '' || !$this->inline) { 194 $this->text = $text; 195 } 196 } 197 198 /** 199 * 200 */ 201 public function getText() { 202 return $this->text; 203 } 204 205 /** 206 * 207 */ 208 public function addReference($reference) { 209 if ($this->id == -1 && !$this->inline) { 210 $this->inline = $reference->isInline(); 211 212 if (!$this->inline) { 213 $this->initId(); 214 } 215 } 216 217 if ($reference->isBackReferenced()) { 218 $this->reference[] = $reference; 219 $this->processed = false; 220 } 221 } 222 223 /** 224 * Checks if the note should be processed 225 */ 226 public function isValid() { 227 return !$this->processed && !empty($this->reference) && $this->text != ''; 228 } 229} 230 231//////////////////////////////////////////////////////////////////////////////////////////////////// 232class refnotes_renderer_note extends refnotes_note { 233 234 /** 235 * 236 */ 237 public function getMinReferenceId() { 238 $result = -1; 239 240 /* References are added in ascending order, so the first valid id should be minimal. */ 241 foreach ($this->reference as $reference) { 242 if ($reference->getId() != -1) { 243 $result = $reference->getId(); 244 break; 245 } 246 } 247 248 return $result; 249 } 250 251 /** 252 * 253 */ 254 public function getAnchorName() { 255 $result = 'refnotes'; 256 $result .= $this->scope->getName(); 257 $result .= ':note' . $this->id; 258 259 return $result; 260 } 261 262 /** 263 * 264 */ 265 public function render($mode) { 266 $doc = $this->scope->getRenderer()->renderNote($mode, $this, $this->reference); 267 268 $this->reference = array(); 269 $this->processed = true; 270 271 return $doc; 272 } 273} 274 275//////////////////////////////////////////////////////////////////////////////////////////////////// 276class refnotes_action_note extends refnotes_note { 277 278 /** 279 * Constructor 280 */ 281 public function __construct($scope, $namespaceName, $name) { 282 parent::__construct($scope, $namespaceName, $name); 283 284 $this->loadDatabaseDefinition(); 285 286 $this->inline = $this->getAttribute('inline', false); 287 } 288 289 /** 290 * 291 */ 292 private function loadDatabaseDefinition() { 293 $name = $this->namespaceName . $this->name; 294 $note = refnotes_reference_database::getInstance()->findNote($name); 295 296 if ($note != NULL) { 297 $this->attributes = $note->getAttributes(); 298 $this->data = $note->getData(); 299 } 300 } 301 302 /** 303 * 304 */ 305 public function addReference($reference) { 306 parent::addReference($reference); 307 308 $exclude = $this->scope->getRenderer()->getReferencePrivateDataSet(); 309 $data = array_diff_key($reference->getData(), array_flip($exclude)); 310 $this->data = array_merge($this->data, $data); 311 } 312 313 /** 314 * Checks if the note should be processed. Simple notes are also reported as valid so that 315 * scope limits will produce note blocks identical to ones during rendering. 316 */ 317 public function isValid() { 318 return !$this->processed && !empty($this->reference) && ($this->text != '' || $this->hasData()); 319 } 320 321 /** 322 * Inject reference database data into references so that they can be properly rendered. 323 * Inject note text into the first reference. 324 */ 325 public function rewriteReferences() { 326 if ($this->text == '' && $this->hasData()) { 327 foreach ($this->reference as $reference) { 328 $reference->rewrite($this->attributes, $this->data); 329 } 330 331 $this->reference[0]->setNoteText($this->scope->getRenderer()->renderNoteText($this)); 332 } 333 334 $this->processed = true; 335 } 336} 337