File: Properties.php

package info (click to toggle)
bamboo 1.2-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 580 kB
  • ctags: 1,338
  • sloc: php: 4,061; makefile: 44; sh: 36
file content (357 lines) | stat: -rw-r--r-- 9,660 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
<?php

/******************************
 
Class: Properties
Hierarchical property storage designed for fast caching of properties.
Properties is a singleton (there is only ever one instance).

There are basically just three functions: get, set, commit. The Properties
object is not in charge of actually storing this values, it simply caches them.
It is the PageStorage object's job to store the values.

Every time you need a page property, you should ask the Properties object.

For example:

  $title = $properties->get('title',$page);
  
or, for convenience:

  $title = $page->get('title');
  
Which will do the same thing.
  
If the Properties cache is not older than the file storage, it returns the
cached value. Otherwise, it asks the PageStore for the value, caches it, then
returns the value.

note: the properties 'content' and 'name' are handled by the pagestore and not
by the properties object at all.

******************************/

require_once('Page.php');

class Properties {

var $data = array(
	'default' => array(
		'pagebackend' => 'folder',
#		'userbackend' => 'sqlite, .bamboo/b.users.sqlite',
		'userbackend' => 'none',
		'indexbackend' => 'sqlite, .bamboo/b.index.sqlite',
		'cachedir' => '/tmp/bamboocache',
		'sitename' => 'Untitled Site',
		'siteroot' => '',
		'decorator' => 'default',
		'liburl' => '/bamboo',
		'access-view' => 'anonymous',
		'access-edit' => 'anonymous',
		'title-prefix' => '',
		'static' => true,
		'mtime' => '1',
		'locked' => false,
		'title' => '$name',
		'nav-title' => '$title',
		'type' => 'txt',
		'dir' => false,
		'index' => true,
		'visible' => true,
		'allowed-types' => 'txt',
		'default-lang' => 'en',
		'languages' => 'en',
	)
);

# props which are always global
var $globals = array(
	'cachedir','sitename','siteroot','pagestore','default-lang'
);

# props which cannot be inherited
var $basic = array(
	'name','title','subject','keywords','description','static','dir','mtime','locked','type','visible'
);

# props which might have translations
var $multilingual = array(
	'title', 'subject', 'description', 'keywords',
);

# 
var $proptypes = array(
	'dir' => 'boolean'
);


function Properties($site_config_file) {	
	if (!is_file($site_config_file))
		die("The site configuration file '$site_config_file' does not exist.");
	if (!is_readable($site_config_file))
		die("The site configuration file '$site_config_file' could not be read.");

	# so many roots:
	#   sitedocroot == the filesystem path to the root of the site
	#   docroot     == apache's configuration for DocumentRoot.
	#   siteroot    == the url of the root of this site.
	
	$sitedocroot = dirname($site_config_file);
	$docroot = preg_replace('#/$#','',$_SERVER['DOCUMENT_ROOT']); // trim trailing slash
	if ($sitedocroot == $docroot)
		$siteroot = '';
	else
		$siteroot = preg_replace("'^$docroot'",'',$sitedocroot);
		
	$this->data['site'] = parse_ini_file($site_config_file);
	$site = & $this->data['site'];
	if (!isset($site['siteroot']))
		$site['siteroot'] = $siteroot;
	elseif ($site['siteroot'] == '/')
		$site['siteroot'] = '';
		
	if (!isset($site['sitedocroot']))
		$site['sitedocroot'] = $sitedocroot;
	
	// because i am lazy and don't want to write them out 'prop' => 'true'
	// should be removed in the future.
	$this->globals = array_flip($this->globals);
	$this->basic = array_flip($this->basic);
	$this->multilingual = array_flip($this->multilingual);
}

function &get($prop, &$page, $recursive_count=0) {
	$value = null;
	$ps = &$page->ps;
	$siteroot = $this->getGlobal('siteroot');
	
	if ($this->is_global($prop)) {
		$value = $this->getGlobal($prop);
	}
	
	## handle basic

	$id = $page->path;
	// if memory cache empty, load data
	if ( !isset( $this->data[$id]['basic'] ) ) {
		$this->data[$id]['basic'] = $ps->loadbasic($siteroot,$page->path);
	}
	if ($this->is_multilingual($prop)) {
		if ($value == null) {
			$prop_dot_lang = find_multilingual_prop($prop, $this->data[$id]['basic']);
			if (isset($this->data[$id]['basic'][$prop_dot_lang]))
				$value = &$this->data[$id]['basic'][$prop_dot_lang];
		}
	}
	if ($value == null) {
		if (isset($this->data[$id]['basic'][$prop]))
			$value = &$this->data[$id]['basic'][$prop];
	}
	
	## handle inheritable

	if ($value == null) {
		$id = '';
		$parentid = '';
		$patharray = split('/',$page->path);
		foreach($patharray as $pathelement) {
			if ($pathelement == '')
				$id = '';
			else
				$id = "$id/$pathelement";
			if ( !isset( $this->data[$id]['inherit'] ) ) {
				if ( !isset($this->data[$parentid]['inherit']) ) {
					$this->data[$id]['inherit'] = $ps->loadinherit($siteroot,$id);
				}
				else {
					// with array_merge, the second arg overwrites the first
					// if the key is the same. hence, inheritence.
					$this->data[$id]['inherit'] = array_merge(
						$this->data[$parentid]['inherit'],
						$ps->loadinherit($siteroot,$id)
					);
				}
			}
			$parentid = $id;
		}
		if (isset($this->data[$id]['inherit'][$prop]))
			$value = &$this->data[$id]['inherit'][$prop];
	}
	
	if ($value == null)
		$value = $this->getGlobal($prop); // last ditch effort.
	
	if ($value != null && $value{0} == '$' && $recursive_count < 4) {
		return $this->get(substr($value,1),$page,$recursive_count+1);
	}
	return $value;
}

/**
 * returns all properties which exist for a particular page.
 * returns (for example): 
 * array(
 *   'visible' => array('value'=>'true','inherit'=>true,'type'=>'boolean')
 *   ...
 * ); 
 **/
function getAll(&$page) {
	$id = $page->path;
	$ps = &$page->ps;
	$siteroot = $this->getGlobal('siteroot');
	$ret = array();

	if ( !isset( $this->data[$id]['basic'] ) ) {
		$this->data[$id]['basic'] = $ps->loadbasic($siteroot,$page->path);
	}
	foreach($this->data[$id]['basic'] as $prop => $value) {
		$ret[$prop] = array('value'=>$value,'inherit'=>false);
	}
	
	$id = '';
	$parentid = '';
	$patharray = split('/',$page->path);
	foreach($patharray as $pathelement) {
		if ($pathelement == '')
			$id = '';
		else
			$id = "$id/$pathelement";
		if ( !isset( $this->data[$id]['inherit'] ) ) {
			if ( !isset($this->data[$parentid]['inherit']) ) {
				$this->data[$id]['inherit'] = $ps->loadinherit($siteroot,$id);
			}
			else {
				// with array_merge, the second arg overwrites the first
				// if the key is the same. hence, inheritence.
				$this->data[$id]['inherit'] = array_merge(
					$this->data[$parentid]['inherit'],
					$ps->loadinherit($siteroot,$id)
				);
			}
		}
		$parentid = $id;
	}

	if (is_array($this->data[$id]['inherit'])) {
		foreach($this->data[$id]['inherit'] as $prop => $value) {
			$ret[$prop] = array('value'=>$value,'inherit'=>true);
		}
	}

	return $ret;
}

function set($propname, $data, &$page) {
	$id = $page->path;
	if ($this->is_multilingual($propname))
		$propnamepluslang = $propname . '.' . $_SESSION['lang'];
	else
		$propnamepluslang = $propname;
	
	if ($data == 'true')
		$data = true;
	elseif ($data == 'false')
		$data = false;

	if ($this->is_basic($propname)) {
		$this->data[$id]['basic'][$propnamepluslang] = $data;
	}
	else {
		$this->data[$id]['inherit'][$propnamepluslang] = $data;
	}
}

function commit(&$page) {
	$id = $page->path;
	$ar = array();
	$siteroot = $this->getGlobal('siteroot');
	$basicprops = array_keys($this->basic);
	$basicprops = array_merge($basicprops, array_keys($this->data[$id]['basic']));
	foreach($basicprops as $prop) {
		if ($this->is_multilingual($prop))
			$prop = $prop . '.' . $_SESSION['lang'];
		if (isset($this->data[$id]['basic'][$prop]))
			$ar[$prop] = $this->data[$id]['basic'][$prop];
	}
	
	$err = $page->ps->savebasic($siteroot,$page->path,$ar);

	## TODO: save b.inherit too ##
#	if ($err == '')
#		$err = $page->ps->saveinherit($siteroot,$page->path,$ar);
	return $err;
}

/*
 * returns the value of a global property
 * (the same for all pages)
 */
function getGlobal($propname) {
	$value = isset($this->data['default'][$propname]) ? $this->data['default'][$propname] : null;
	$value = isset($this->data['site'][$propname]) ? $this->data['site'][$propname] : $value;
	return $value;
}

function is_global($prop) {
	return array_key_exists($prop,$this->globals);
}

function is_basic($prop) {
	return array_key_exists($prop,$this->basic);
}

function is_multilingual($prop) {
	return array_key_exists($prop,$this->multilingual);
}

function proptype($prop) {
	if (isset($this->proptypes[$prop]))
		return $this->proptypes[$prop];
	else
		return '';
}

} // end class


/* 
 * tries to guess the filename of the site configuration file
 */
function get_site_config() {
	$docroot = preg_replace('#/$#','',$_SERVER['DOCUMENT_ROOT']); // trim trailing slash
	
	# note: i think that script_url and path_translated will always return
	# bamboo in apache2, and are therefor useless. apache1 is different.
	
	if (isset($_SERVER['REQUEST_URI']))
		$path = $docroot . $_SERVER['REQUEST_URI'];	
	elseif (isset($_SERVER['REDIRECT_URL']))
		$path = $docroot . $_SERVER['REDIRECT_URL'];
	elseif (isset($_SERVER['SCRIPT_URL']))
		$path = $docroot . $_SERVER['SCRIPT_URL'];
	else
		$path = $_SERVER['PATH_TRANSLATED']; // comes with docroot (eg /var/www)
	
	# get only the top level of the path
	# (strip off docroot and subfolders)
	$path = preg_replace("#^$docroot(/.*?)(/.*)?$#", '$1', $path);
	
	if (is_file("$docroot/b.site"))
		return "$docroot/b.site";
	else
		return "$docroot{$path}/b.site";
}

function find_multilingual_prop($prop, $properties) {
	$languages = Lang::priority();
	$lang_len = count( $languages );
	$i = 0;
	$prop_dot_lang = $prop . '.' . $languages[$i];
	while( !isset( $properties[$prop_dot_lang] ) && ( $i < $lang_len ) ) {
		$prop_dot_lang = $prop . '.' . $languages[ $i++ ];
	}
	return $prop_dot_lang;
}

return;
?>