*/ require_once(DOKU_PLUGIN . 'refnotes/locale.php'); require_once(DOKU_PLUGIN . 'refnotes/config.php'); require_once(DOKU_PLUGIN . 'refnotes/refnote.php'); require_once(DOKU_PLUGIN . 'refnotes/reference.php'); require_once(DOKU_PLUGIN . 'refnotes/note.php'); require_once(DOKU_PLUGIN . 'refnotes/namespace.php'); require_once(DOKU_PLUGIN . 'refnotes/scope.php'); require_once(DOKU_PLUGIN . 'refnotes/rendering.php'); require_once(DOKU_PLUGIN . 'refnotes/database.php'); //////////////////////////////////////////////////////////////////////////////////////////////////// class refnotes_parser_core { private static $instance = NULL; private $context; private $lexer; private $handler; /** * */ public static function getInstance() { if (self::$instance == NULL) { self::$instance = new refnotes_parser_core(); } return self::$instance; } /** * Constructor */ public function __construct() { /* Default context. Should never be used, but just in case... */ $this->context = array(new refnotes_parsing_context()); $this->lexer = NULL; $this->handler = NULL; } /** * */ public function registerLexer($lexer) { $this->lexer = $lexer; } /** * */ public function enterParsingContext() { $this->context[] = new refnotes_parsing_context(); } /** * */ public function exitParsingContext($handler) { $this->handler = $handler; unset($this->context[count($this->context) - 1]); } /** * */ public function getInstructions($text) { $this->callWriter = new refnotes_nested_call_writer($this->handler->getCallWriter(), $this->handler); $this->callWriter->connect(); $this->lexer->parse($text); $this->callWriter->disconnect(); return $this->callWriter->calls; } /** * */ private function getCurrentContext() { return end($this->context); } /** * */ public function canHandle($state) { return $this->getCurrentContext()->canHandle($state); } /** * */ public function enterReference($name, $data) { $this->getCurrentContext()->enterReference($name, $data); } /** * */ public function exitReference() { return $this->getCurrentContext()->exitReference(); } } //////////////////////////////////////////////////////////////////////////////////////////////////// class refnotes_parsing_context { private $handling; private $reference; /** * Constructor */ public function __construct() { $this->reset(); } /** * */ private function reset() { $this->handling = false; $this->reference = NULL; } /** * */ public function canHandle($state) { switch ($state) { case DOKU_LEXER_ENTER: $result = !$this->handling; break; case DOKU_LEXER_EXIT: $result = $this->handling; break; default: $result = false; break; } return $result; } /** * */ public function enterReference($name, $data) { $this->handling = true; $this->reference = new refnotes_parser_reference($name, $data); } /** * */ public function exitReference() { $reference = $this->reference; $this->reset(); return $reference; } } //////////////////////////////////////////////////////////////////////////////////////////////////// abstract class refnotes_core { protected $presetStyle; protected $namespace; protected $mapping; /** * Constructor */ public function __construct() { $this->presetStyle = refnotes_configuration::load('namespaces'); $this->namespace = array(); $this->mapping = array(); } /** * */ public function getNamespaceCount() { return count($this->namespace); } /** * Returns a namespace given it's name. The namespace is created if it doesn't exist yet. */ public function getNamespace($name) { $result = $this->findNamespace($name); if ($result == NULL) { $result = $this->createNamespace($name); } return $result; } /** * Finds a namespace given it's name */ protected function findNamespace($name) { $result = NULL; if (array_key_exists($name, $this->namespace)) { $result = $this->namespace[$name]; } return $result; } /** * Finds a namespace or it's parent */ public function findParentNamespace($name) { while (($name != '') && !array_key_exists($name, $this->namespace)) { $name = refnotes_namespace::getParentName($name); } return ($name != '') ? $this->namespace[$name] : NULL; } /** * */ public function styleNamespace($namespaceName, $style) { $namespace = $this->getNamespace($namespaceName); if (array_key_exists('inherit', $style)) { $source = $this->getNamespace($style['inherit']); $namespace->inheritStyle($source); } $namespace->setStyle($style); } /** * */ public function setNamespaceMapping($namespaceName, $map) { foreach ($map as $ns) { $this->mapping[$ns] = $namespaceName; } } /** * */ protected function clearNamespaceMapping($namespaceName) { $this->mapping = array_diff($this->mapping, array($namespaceName)); } /** * */ protected function createNamespace($name) { if ($name != ':') { $parentName = refnotes_namespace::getParentName($name); $parent = $this->getNamespace($parentName); $this->namespace[$name] = new refnotes_namespace($name, $parent); } else { $this->namespace[$name] = new refnotes_namespace($name); } if (array_key_exists($name, $this->presetStyle)) { $this->namespace[$name]->setStyle($this->presetStyle[$name]); } return $this->namespace[$name]; } /** * */ protected function getNote($namespaceName, $noteName) { $scope = $this->getNamespace($namespaceName)->getActiveScope(); $note = $scope->findNote($namespaceName, $noteName); if (($note == NULL) && array_key_exists($namespaceName, $this->mapping)) { $scope = $this->getNamespace($this->mapping[$namespaceName])->getActiveScope(); $note = $scope->findNote($namespaceName, $noteName); } if ($note == NULL) { if (!is_int($noteName)) { $note = $this->createNote($scope, $namespaceName, $noteName); $scope->addNote($note); } else { $note = new refnotes_note_mock(); } } return $note; } /** * */ abstract protected function createNote($scope, $namespaceName, $noteName); } //////////////////////////////////////////////////////////////////////////////////////////////////// class refnotes_renderer_core extends refnotes_core { private static $instance = NULL; private $leftoversRenderingBlocks = 0; /** * Renderer core is used by both references and notes syntax plugins during the rendering * stage. The instance has to be shared between the plugins, and since there should be no * more than one rendering pass during a DW page request, a single instance of the syntax * core should be enough. */ public static function getInstance() { if (self::$instance == NULL) { self::$instance = new refnotes_renderer_core(); } return self::$instance; } /** * */ public function addReference($attributes, $data) { $note = $this->getNote($attributes['ns'], $attributes['name']); $reference = new refnotes_renderer_reference($note, $attributes, $data); $note->addReference($reference); return $reference; } /** * */ public function renderNotes($mode, $namespaceName, $limit) { $html = ''; if ($namespaceName == '*') { if ($this->leftoversRenderingBlocks == 0) { foreach ($this->namespace as $namespace) { $html .= $namespace->renderNotes($mode); } } } else { $this->clearNamespaceMapping($namespaceName); $namespace = $this->findNamespace($namespaceName); if ($namespace != NULL) { $html = $namespace->renderNotes($mode, $limit); } } return $html; } /** * Keep track of leftover note rendering blocking on included pages */ public function updateRenderingBlocks($block) { switch ($block) { case 'enter': ++$this->leftoversRenderingBlocks; break; case 'exit': if ($this->leftoversRenderingBlocks > 0) { --$this->leftoversRenderingBlocks; } break; } } /** * */ protected function createNote($scope, $namespaceName, $noteName) { return new refnotes_renderer_note($scope, $namespaceName, $noteName); } } //////////////////////////////////////////////////////////////////////////////////////////////////// class refnotes_action_core extends refnotes_core { private $styleStash; private $mappingStash; /** * Constructor */ public function __construct() { parent::__construct(); $this->styleStash = new refnotes_namespace_style_stash($this); $this->mappingStash = new refnotes_namespace_mapping_stash(); } /** * */ public function markScopeStart($namespaceName, $callIndex) { $this->getNamespace($namespaceName)->markScopeStart($callIndex); } /** * */ public function markScopeEnd($namespaceName, $callIndex) { $this->getNamespace($namespaceName)->markScopeEnd($callIndex); } /** * Collect styling information from the page */ public function addStyle($namespaceName, $style) { $this->styleStash->add($this->getNamespace($namespaceName), $style); } /** * */ public function getStyles() { return $this->styleStash; } /** * Collect mapping information from the page */ public function addMapping($namespaceName, $map) { $this->mappingStash->add($this->getNamespace($namespaceName), $map); } /** * */ public function getMappings() { return $this->mappingStash; } /** * */ public function reset() { $this->namespace = array(); } /** * */ public function addReference($attributes, $data, $call) { $note = $this->getNote($attributes['ns'], $attributes['name']); $reference = new refnotes_action_reference($note, $attributes, $data, $call); $note->addReference($reference); return $reference; } /** * */ public function rewriteReferences($namespaceName, $limit) { $this->clearNamespaceMapping($namespaceName); if ($namespaceName == '*') { foreach ($this->namespace as $namespace) { $namespace->rewriteReferences(); } } else { $namespace = $this->findNamespace($namespaceName); if ($namespace != NULL) { $namespace->rewriteReferences($limit); } } } /** * */ protected function createNote($scope, $namespaceName, $noteName) { return new refnotes_action_note($scope, $namespaceName, $noteName); } }