1<?php
2/**
3 * DokuWiki Plugin workflow (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Ryan Boder <ryan.boder@suretycam.com>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12function startswith($haystack, $needle) {
13  return $needle === "" || strpos($haystack, $needle) === 0;
14}
15
16function wf_render_link($ns, $page, $onclick, $text) {
17  $exists = false;
18  resolve_pageid('wf', $page, $exists);
19  $exists = $exists ? '1' : '2';
20  return "<a class=\"wikilink$exists\" title=\"$page\" href=\"doku.php?id=$page\" onclick=\"$onclick\">$text</a>";
21}
22
23function wf_render_criteria($criteria) {
24  $data = '';
25  foreach ($criteria as $name => $value) {
26    $data .= $name . '=' . $value . ':';
27  }
28  return trim($data, ':');
29}
30
31class syntax_plugin_workflow_decision extends DokuWiki_Syntax_Plugin {
32
33    public function getType() { return 'formatting'; }
34    public function getPType() { return 'block'; }
35    public function getSort() { return 196; }
36
37    public function connectTo($mode) {
38      $this->Lexer->addEntryPattern('<decision.*?>(?=.*?</decision>)',$mode,'plugin_workflow_decision');
39    }
40
41    public function postConnect() {
42      $this->Lexer->addExitPattern('</decision>','plugin_workflow_decision');
43    }
44
45    public function handle($match, $state, $pos, &$handler){
46      $data = array($state, $match);
47
48      return $data;
49    }
50
51    public function render($mode, &$renderer, $indata) {
52      if($mode != 'xhtml') return false;
53
54      if (empty($indata)) return false;
55      list($state, $data) = $indata;
56
57      global $INFO;
58      include DOKU_INC . 'lib/plugins/workflow/wfversion.php';
59      $wfns = trim($this->getConf('WorkflowNamespace'));
60
61      switch ($state) {
62      case DOKU_LEXER_ENTER:
63	// get the attributes
64	$numattrs = preg_match_all('/([\w\d]+)="([\w\d, \/_-]+)"/', $data, $matches);
65	$attrs = array();
66	for ($i = 0; $i < $numattrs; $i++) {
67	  $attrs[$matches[1][$i]] = $matches[2][$i];
68	}
69	$renderer->doc .= '<script>';
70	$renderer->doc .= 'var wfnamespace = ' . json_encode($wfns) . ';';
71	$renderer->doc .= 'var wfpageid = ' . json_encode(substr($INFO['id'], strlen($wfns) + 1)) . ';';
72	$renderer->doc .= 'var wfstatedefs = ' . json_encode($attrs) . ';';
73	$renderer->doc .= '</script>';
74	$renderer->doc .= '<div class="wfsearch"><a href="#wfsearch" onclick="wfFocusSearch();" title="Workflow Decision"><div class="wfsearchx"></div></a></div>';
75	$renderer->doc .= '<input type="text" id="wfsearch" placeholder="Type to search">';
76	$renderer->doc .= ' <span style="color:#919191;">workflow version ' . $workflow_plugin_version . '</span><br/>';
77	$renderer->doc .= '<table id="wftable">';
78	break;
79      case DOKU_LEXER_UNMATCHED:
80	// foreach decision link
81	$lines = explode("\n  *", $data);
82	foreach ($lines as $rawline) {
83	  // parse the line
84	  $line = trim($rawline);
85	  if ($line == '') continue;
86	  $tokens = preg_split('/(\|| \+| -| \?)/', $line, NULL, PREG_SPLIT_DELIM_CAPTURE);
87
88	  // get the page name and link text
89	  $page = trim($tokens[0]);
90	  $text = in_array('|', $tokens) ? trim($tokens[2]) : $page;
91	  $options_index = in_array('|', $tokens) ? 3 : 1; // the index of the first option
92
93	  // process new workflow state and criteria for the link
94	  $criteria = array();
95	  $onclick = '';
96	  for ($i = $options_index; $i+1 < count($tokens); $i += 2) {
97	    list($name, $value) = array_map('trim', explode('=', $tokens[$i+1]));
98	    if ($tokens[$i] == ' +' && $name != NULL && $value != NULL) {
99	      $onclick .= 'wfRemember(\'' . $name . '\',\'' . $value . '\');';
100	    } else if ($tokens[$i] == ' -' && $name != NULL) {
101	      $onclick .= 'wfForget(\'' . $name . '\');';
102	    } else if ($tokens[$i] == ' ?' && $name != NULL && $value != NULL) {
103	      $criteria[$name] = $value;
104	    }
105	  }
106
107	  $renderer->doc .= "<tr data-criteria=\"" . wf_render_criteria($criteria) . "\"><td>" . wf_render_link($wfns, $page, $onclick, $text) . "</td></tr>";
108	}
109
110	break;
111      case DOKU_LEXER_EXIT:
112	$renderer->doc .= '</table>';
113	break;
114      default:
115	$renderer->doc .= '!!!Renderer default case!!!';
116      }
117
118      return true;
119    }
120
121}
122