1<?php
2/**
3 * common.php : helper functions used by both global and local components of the directions plug-in.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Nuno Flores (nuno.flores@gmail.com)
7 *
8 */
9
10/**
11 * parseHitsFile
12 *
13 * This function parse the hits file and returns an associative array with all the steps and their occurrences.
14 *
15 */
16    function dir_parseHitsFile($filename, $registeredOnly=false) {
17
18		// open hits file
19		if (!file_exists($filename)){
20	        $ErrorMsg  = 'directions plug-in error: ';
21	        $ErrorMsg .= 'The given file ' . $filename . ' does not exist!';
22	        die($ErrorMsg);
23	    }
24
25		// FIXME: When file is too big, might need performance tweaks
26	    $content = file($filename);
27
28		// results array
29	    $data = array();
30
31		// parse contents
32
33		$delimiter = '>';
34
35		//last step by user
36		$laststep = array();
37
38		$user = '';
39		$source = '';
40		$target = '';
41		foreach ($content as $line) {
42			$path = explode($delimiter,$line);
43			if (sizeof($path) == 3) {
44				$user = $path[0];
45				$source = trim($path[1]);
46				$target = trim($path[2]);
47			} else {
48				$data['errorcount']++;
49			}
50
51			// guard clauses
52
53			// unautheticated user
54			if ($registeredOnly)
55				if (strcmp($user ,'-') == 0) continue;
56
57			// one of the pages doesn't exist
58			if ((!page_exists(str_replace('/',':',$source))) || (!page_exists(str_replace('/',':',$target)))) continue;
59
60			// BUG: This is still not workin properly...
61			// self-reference
62			if (strcmp($source, $target) == 0) {
63				continue;
64			}
65
66			// check for valid STEP
67			if (!isset($lastmove[$user])) {
68				$lastmove[$user] = array();
69				$lastmove[$user]['source'] = '';
70				$lastmove[$user]['target'] = '';
71			}
72
73			if ((strcmp($source,$lastmove[$user]['source']) != 0) ||
74				(strcmp($target,$lastmove[$user]['target']) != 0)) {
75					// compose step string
76					$step = trim($source).'->'.trim($target);
77					//error_log("step: ".$step);
78					if (!isset($data[$step])) {
79						$data[$step] = 1;
80					} else {
81						$data[$step]++;
82					}
83			}
84			$lastmove[$user]['source'] = $source;
85			$lastmove[$user]['target'] = $target;
86		}
87        return $data;
88	}
89
90/**
91 * generateDirections
92 * This function produces the directions (incoming/outgoing pages) for a particular wiki page.
93 *
94 */
95    function dir_generateDirections($info, $data, $fanInOnly=false, $fanOutOnly=false, $showGraph=true) {
96		// get current page id (name with namespace)
97		$id = getID();
98		// parse data to find fan in and fan out
99		// $data comes has associative array with step string (page1->page2) on "key" and occurences of step in "value".
100		// find relevant steps first, order by ocurrences second.
101		$graph = array();
102		foreach ($data as $key=>$value) {
103			$pages = explode("->", $key);
104			$page1 = str_replace('/',':',$pages[0]);$page1 = trim($page1);
105			$page2 = str_replace('/',':',$pages[1]);$page2 = trim($page2);
106			if (strcmp($id,$page1) == 0) {
107				$index = $page1.'->'.$page2;
108			    $graph[$index] = $value;
109				$fanOut[$page2] = $value;
110			}
111			if (strcmp($id,$page2) == 0) {
112				$index = $page1.'->'.$page2;
113			    $graph[$index] = $value;
114				$fanIn[$page1] = $value;
115			}
116			//sort
117			if (isset($fanOut)) arsort($fanOut);
118			if (isset($fanIn)) arsort($fanIn);
119		}
120		// return (printable) results
121		$results .= dir_prettyPrintResults($fanIn, $fanInOnly, $fanOut, $fanOutOnly);
122
123		if ($showGraph) {
124			if(!in_array('graphviz',plugin_list())) {
125				$results .= '<span class="notify">To view the graph the graphviz plug-in must be installed.</span>';
126			} else {
127				//graph
128				$results .= dir_generateGraph($info, $graph);
129			}
130		}
131
132		return $results;
133    }
134/**
135* generateListofJumps
136*
137* prints out the table of 'jumps' of the whole wiki.
138*
139*/
140    function dir_generateListofJumps($data) {
141		global $conf;
142		$trimLimit = $conf['plugin']['directions']['trim_limit'];
143
144		$output = '<div class=jumps_dbox>';
145		$output .= '<table class=jumps_dbox_table>';
146		$output .= '<tr><td class=jumps_dbox_table_title_column colspan="3">Jumps</td></tr>';
147		$output .= '<tr><td class=jumps_dbox_table_title_from_column >From</td>';
148		$output .= '<td class=jumps_dbox_table_title_count_column>Times</td>';
149		$output .= '<td class=jumps_dbox_table_title_to_column>To</td></tr>';
150
151		//sort descendently
152		arsort($data);
153
154		foreach ($data as $key=>$value) {
155			$pages = explode("->", $key);
156			$page1 = str_replace('/',':',$pages[0]);
157			$page2 = str_replace('/',':',$pages[1]);
158
159			$output .= '<tr><td class=jumps_dbox_table_from_column >';
160
161			$output .= '<a ';
162			$output .= 'title="'.$page1.'" ';
163			$output .= 'href="'.wl($page1).'">'.dir_trimPageTitle(dir_get_first_heading($page1),$trimLimit).'</a>';
164
165			$output .= '</td><td class=jumps_dbox_table_count_column >';
166
167			$output .= $value;
168
169			$output .= '</td><td class=jumps_dbox_table_to_column >';
170
171			$output .= '<a ';
172			$output .= 'title="'.$page2.'" ';
173			$output .= 'href="'.wl($page2).'">'.dir_trimPageTitle(dir_get_first_heading($page2),$trimLimit).'</a>';
174
175			$output .= '</td></tr>';
176		}
177
178		$output .='</table>';
179		$output .='</div>';
180		return $output;
181	}
182
183	/**
184	* dir_prettyPrintResults
185	*
186	* helper function that enables optional printing of "incoming" or "outgoing" (or both) sections of the directions table.
187	*
188	*/
189
190    function dir_prettyPrintResults($fanIn, $fanInOnly, $fanOut, $fanOutOnly, $trimLimit) {
191
192		global $conf;
193		$maxdirections = $conf['plugin']['directions']['max_directions'];
194		if (!isset($trimLimit))	$trimLimit = $conf['plugin']['directions']['trim_limit'];
195		$limit = $maxdirections;
196
197
198		if ($fanInOnly) {
199			$output .= '<table class=directions_dbox_table>';
200			$output .= '<tr><td class=directions_dbox_table_title_incoming_column >Incoming</td></tr>';
201			$output .= '<tr><td class=directions_dbox_table_incoming_column >';
202			// fan in
203			foreach ($fanIn as $key=>$value) {
204				$output .= '<a ';
205				$output .= 'title="'.$key.'" ';
206				$output .= 'href="'.wl($key).'">'.dir_trimPageTitle(dir_get_first_heading($key),$trimLimit).'</a>';
207				$output .= '<span class=directions_dbox_occurrences >('.$value.')</span> -></br>';
208				$limit--;
209				if ($limit == 0) break;
210			}
211			$output .= '</td></tr>';
212			$output .='</table>';
213			return $output;
214		}
215
216		if ($fanOutOnly) {
217			$output .= '<table class=directions_dbox_table>';
218			$output .= '<tr><td class=directions_dbox_table_title_outgoing_column>Outgoing</td></tr>';
219			$output .= '<tr><td class=directions_dbox_table_outgoing_column >';
220			// fan out
221			foreach ($fanOut as $key=>$value) {
222				$output .= '-> <a ';
223				$output .= 'title="'.$key.'" ';
224				$output .= 'href="'.wl($key).'">'.dir_trimPageTitle(dir_get_first_heading($key),$trimLimit).'</a>';
225				$output .= '<span class=directions_dbox_occurrences >('.$value.')</span></br>';
226				$limit--;
227				if ($limit == 0) break;
228			}
229			$output .= '</td></tr>';
230			$output .='</table>';
231			return $output;
232
233		}
234
235		$output = '<div class=directions_dbox>';
236		$output .= '<table class=directions_dbox_table>';
237		$output .= '<tr><td class=directions_dbox_table_title_column colspan="2">Directions</td></tr>';
238		$output .= '<tr><td class=directions_dbox_table_title_incoming_column >Incoming</td>';
239		$output .= '<td class=directions_dbox_table_title_outgoing_column>Outgoing</td></tr>';
240		$output .= '<tr><td class=directions_dbox_table_incoming_column >';
241		// fan in
242		foreach ($fanIn as $key=>$value) {
243			$output .= '<a ';
244			$output .= 'title="'.$key.'" ';
245			$output .= 'href="'.wl($key).'">'.dir_trimPageTitle(dir_get_first_heading($key),$trimLimit).'</a>';
246			$output .= '<span class=directions_dbox_occurrences >('.$value.')</span> -></br>';
247			$limit--;
248			if ($limit == 0) break;
249		}
250		$limit = $maxdirections;
251		$output .= '</td><td class=directions_dbox_table_outgoing_column >';
252		// fan out
253		foreach ($fanOut as $key=>$value) {
254			$output .= '-> <a ';
255			$output .= 'title="'.$key.'" ';
256			$output .= 'href="'.wl($key).'">'.dir_trimPageTitle(dir_get_first_heading($key),$trimLimit).'</a>';
257			$output .= '<span class=directions_dbox_occurrences >('.$value.')</span></br>';
258			$limit--;
259			if ($limit == 0) break;
260		}
261		$output .= '</td></tr>';
262		$output .='</table>';
263		$output .='</div>';
264		return $output;
265	}
266
267	/**
268	* dir_get_first_heading
269	*
270	* return the first heading of a page or, if nonexistant, the name of the page.
271	*
272	*/
273
274	function dir_get_first_heading($page) {
275		$heading = p_get_first_heading($page);
276		if (!isset($heading)) $heading = $page;
277		return $heading;
278	}
279
280	/**
281	* dir_trimPageTitle
282	*
283	* trims the title of a page by $maxchars visible. Useful to printout title names as a preview...
284	*
285	*/
286
287	function dir_trimPageTitle($title, $maxchars=19) {
288		if (strlen($title) > $maxchars)	return substr($title,0,$maxchars).'...';
289		return $title;
290	}
291?>
292