1<?php
2
3require_once(dirname(__FILE__).'/../../lib/plugins.php');
4
5class projects_plugin_plot_dependency extends Plugin {
6	/**
7	 * The name of the parser, a human readable string, a unique identifier
8	 */
9	public function name() { return "Plot Dependency"; }
10
11	/**
12	 * whether this parser can make a given target
13	 */
14	public function can_handle($project, $file) {
15		if ($file->is_target()) return false;
16		return has_extension($file->name(), ".plot");
17	}
18
19	public function handle($project, $file) {
20		$plot = new PlotDefinition($file->attributes());
21		$plot->add_content($file->content());
22		return $plot;
23	}
24
25}
26
27class PlotDefinition extends SourceDefinition {
28	private $properties = array();
29	private $data = NULL;
30	private $columns = array();
31	private $line_styles = array();
32	private $axes = array();
33	private $valid = true;
34	private $error = NULL;
35
36	public function valid() { return $this->valid; }
37	public function columns() { return $this->columns; }
38	public function error() { return $this->error; }
39
40	public function data_property($property) {
41		return $this->data[$property];
42	}
43
44	public function column($column) { return $this->columns[$column]; }
45
46	public function property($name) {
47		if (!isset($this->properties[$name])) return NULL;
48		return $this->properties[$name];
49	}
50
51	public function line_style($style_name, $property_name) {
52		$style = $this->line_styles[$style_name];
53		if (!$style) return NULL;
54		return $style[$property_name];
55	}
56
57	public function axis_property($axis_name, $property_name) {
58		$axis = $this->axes[$axis_name];
59		if (!axis) return NULL;
60		return $axis[$property_name];
61	}
62
63	public function __construct($attributes) {
64		parent::__construct($attributes);
65	}
66
67	public function add_content($content) {
68		parent::add_content($content);
69		$lines = explode("\n", $content);
70		foreach ($lines as $line) {
71			$fields = explode('=>', $line);
72			if (count($fields) < 2) continue;
73			$name = trim($fields[0]);
74			// lines started with # are comments
75			if (substr($name, 1, 1) == '#') continue;
76			$value = trim($fields[1]);
77			if ($name == 'data') {
78				$pairs = $this->pairs($value);
79				$data_name = $pairs['name'];
80				if ($data_name) $this->data = $pairs;
81				continue;
82			}
83			if ($name == 'axis') {
84				$pairs = $this->pairs($value);
85				$axis_name = $pairs['name'];
86				if ($axis_name) $this->axes[$axis_name] = $pairs;
87				continue;
88			}
89			// columns are marked as a number or a range as number - number
90			$range = explode('-', $name);
91			if (count($range) == 1) $range[1] = $range[0];
92			if (!is_numeric($range[0])) {
93				$this->properties[$name] = $value;
94				continue;
95			}
96			sort($range);
97			// columns must be numbers
98			foreach ($range as $column) {
99				$column = trim($column);
100				if (!is_numeric($column)) continue 2;
101			}
102			// parse the description which consists of comma separated
103			// pairs of the form name1 = value1, name2 = value2 ...
104			$pairs = $this->pairs($value);
105			if (!isset($pairs['name'])) continue;
106			$style = $pairs['name'];
107			$this->line_styles[$style] = $pairs;
108			if (isset($pairs['as'])) {
109				$use = $pairs['as'];
110				if ($use != 'x' && $use != 'y') continue;
111			}
112			else $use = NULL;
113			for ($i = trim($range[0]); $i <= trim($range[1]); $i++)
114				$this->columns[$i] = $style;
115			if ($use == 'x') $this->properties['x_column'] = trim($range[0]);
116		}
117		if (!$this->data) {
118			$this->error = "No data file.";
119			$this->valid = false;
120			return;
121		}
122		$x_column = $this->property('x_column');
123		if (!$x_column || !is_numeric($x_column)) {
124			$this->error = "No data column specified for x-axis.";
125			$this->valid = false;
126			return;
127		}
128		if (!$this->columns) {
129			$this->error = "No data column.";
130			$this->valid = false;
131			return;
132		}
133		if (!in_array($this->data, $this->dependency()))
134			$this->add_dependency($this->data['name']);
135	}
136
137	private function pairs($string) {
138		$pairs = array();
139		$matched = preg_match_all(
140			'/ *(.*?) *= *(?i:([^\'"]*?)|\'(.*?)\'|"(.*?)") *(,|$)/', $string, $matches, PREG_SET_ORDER);
141		foreach ($matches as $match)
142			$pairs[$match[1]] = $match[2] . $match[3] . stripcslashes($match[4]);
143		return $pairs;
144	}
145}
146?>