PageRenderTime 40ms CodeModel.GetById 12ms app.highlight 17ms RepoModel.GetById 7ms app.codeStats 0ms

/branches/coding-style/fp-plugins/prettyurls/plugin.prettyurls.php

https://bitbucket.org/alexandrul/flatpress
PHP | 599 lines | 347 code | 193 blank | 59 comment | 75 complexity | 9d2ec6026b4f20b11e52a910d36d8663 MD5 | raw file
  1<?php
  2/*
  3Plugin Name: PrettyURLs
  4Plugin URI: http://flatpress.nowherland.it/
  5Description: Url prettifier (powered by htaccess)
  6Author: NoWhereMan  (E.Vacchi)
  7Version: 3.0
  8Author URI: http://www.nowhereland.it
  9*/
 10
 11/**
 12 * Place where the index is stored
 13 */
 14define('PRETTYURLS_TITLES', true);
 15define('PRETTYURLS_PATHINFO', true);
 16define('PRETTYURLS_CACHE', CACHE_DIR . '%%prettyurls-index.tmp');
 17define('PRETTYURLS_CATS', CACHE_DIR . '%%prettyurls-cats.tmp');
 18
 19/**
 20 * File existance check
 21 */
 22
 23# memo
 24# register_plugin_setup('plugin_id', 'setup_func');
 25
 26function plugin_prettyurls_setup() {
 27	
 28	if (file_exists(ABS_PATH . '.htaccess'))
 29		return 1;
 30	
 31	if (!is_writable(ABS_PATH)) {
 32	 	return -2;
 33	}
 34	
 35	return 1;
 36}
 37
 38class Plugin_PrettyURLs {
 39
 40	var $index = array();
 41	var $status = 0;
 42	var $date_handled = false;
 43	var $categories = null;
 44	var $fp_params;
 45	
 46	
 47	function categories($force=true) {
 48		
 49		if ($this->categories) 
 50			return; 
 51		
 52		if ($force || !file_exists(PRETTYURLS_CATS)) {
 53			$d = entry_categories_get('defs');
 54			$list = array();
 55			foreach ($d as $k=>$v) {
 56				$list[$k] = sanitize_title($v);
 57			}
 58			io_write_file(PRETTYURLS_CATS, serialize($list));
 59		} else {
 60			$f = io_load_file(PRETTYURLS_CATS);
 61			$list = unserialize($f);
 62		}
 63		$this->categories = $list;
 64	}
 65	
 66	
 67	function md5($id, $title) {
 68		$date = date_from_id($id);
 69		return md5($date['y'].$date['m'].$date['d'].$title);
 70	}
 71
 72	
 73	
 74	function permalink($str, $id) {
 75		global $fpdb, $post;
 76
 77		if (PRETTYURLS_TITLES)
 78			$title = sanitize_title($post['subject']);
 79		else 
 80			$title = $id;
 81		$date = date_from_id($id);
 82					// yeah, hackish, I know...
 83	
 84		return $this->baseurl  . "20{$date['y']}/{$date['m']}/{$date['d']}/$title/";
 85	}
 86	
 87	function commentlink($str, $id) {
 88		$link = $this->permalink($str, $id);
 89		return $link . "comments/";
 90	}
 91	
 92	function feedlink($str, $type) {
 93		return $this->baseurl  . "feed/{$type}/";
 94		
 95	}
 96	
 97	function commentsfeedlink($str, $type, $id) {
 98		$link = $this->commentlink($str, $id);
 99		return $link . "feed/{$type}/"; 
100	}
101
102
103	function staticlink($str, $id) {
104		return $this->baseurl  .  "$id/";
105	}
106	
107
108	function categorylink($str, $catid) {
109		if (PRETTYURLS_TITLES) {
110			if (@$this->categories[$catid])
111				return $this->baseurl  . "category/{$this->categories[$catid]}/";
112			else return $str;
113		} else {
114			return $this->baseurl  . "category/{$catid}/";
115		}
116	}
117	
118	
119	function yearlink($str, $y) {
120		return $this->baseurl  . "20$y/";
121	}
122	
123	function monthlink($str, $y, $m) {
124		return $this->yearlink($str, $y) . "$m/";
125	}
126	
127	function daylink($str, $y, $m, $d) {
128		return $this->monthlink($str, $y, $m) . "$d/";
129	}
130	
131	
132	function cache_create() {
133		
134		$this->index = array();
135
136		/*
137		$o =& entry_init();
138		
139		$entries = $o->getList();
140		 */
141
142		$o = new FPDB_Query(array('start'=>0,'count'=>-1,'fullparse'=>false), null);
143		
144		
145		#foreach ($entries as $id => $contents) {
146		while ($o->hasMore()) {
147			list($id, $contents) = $o->getEntry();
148			$date = date_from_id($id);
149			echo $contents['subject'], "\n";
150			$md5 = md5(sanitize_title($contents['subject']));
151			$this->index[$date['y']][$date['m']][$date['d']][$md5] = $id;		
152		}
153		#}
154		
155		$this->cache_save();
156		io_write_file(PRETTYURLS_CACHE, 'dummy');
157		
158	}
159	
160
161	
162	
163	function handle_categories($matches) {
164	
165	
166		if (!$this->categories) 
167			return;
168			
169		if (PRETTYURLS_TITLES) {	
170			if ($c = array_search($matches[1], $this->categories))
171				$this->fp_params['cat'] = $c;
172		} else {
173			$this->fp_params['cat'] = $matches[1];
174		}
175		
176	}
177	
178	/*
179		named matches are not supported here
180	*/
181	
182	function handle_date($matches) {
183	
184		$this->fp_params['y'] = $matches[1];
185		if (isset($matches[3])) $this->fp_params['m'] = $matches[3] ;
186		if (isset($matches[5])) $this->fp_params['d'] = $matches[5];
187		
188		$this->date_handled = true;
189		
190	}
191	
192	
193	function handle_static($matches) {
194		$this->fp_params['page'] = $matches[1];
195		$this->status = 2;	
196	}
197	
198	function handle_entry($matches) {
199		
200		if (PRETTYURLS_TITLES) {	
201		
202			#isset($this->index[
203			if ($this->cache_get($this->fp_params['y'],$this->fp_params['m'], $this->fp_params['d'], md5($matches[1]))) {
204				$this->fp_params['entry'] = $this->index[$this->fp_params['y']][$this->fp_params['m']][$this->fp_params['d']][md5($matches[1])];
205			} else {
206				// a bit hackish: we make up a fake url when there is no match, 
207				// so that at the higher level the system will 404... 
208				$this->fp_params['entry'] = 'entry000000-000000'; 
209			}
210		} else {
211			$this->fp_params['entry'] = $matches[1];
212		}
213
214			
215	}
216	
217	function handle_page($matches) {
218		$this->fp_params['paged'] = $matches[1];
219		$this->status = 2;
220	}
221	
222	
223	function handle_comment($matches) {
224		$this->fp_params['comments'] = true;
225	}
226	
227	function handle_feed($matches) {
228	
229		$this->fp_params['feed'] = isset($matches[2])? $matches[2]:'rss2';
230	}
231
232	
233	/*
234	 * here is where the real work is done.
235	 *
236	 * First we load the cache if exists;
237	 *
238	 * We check then if the GET request contains a 'title'
239	 * if so, we'll need date and time to construct the md5 sum
240	 * with which we index the cache array
241	 *
242	 * If that entry exists, we set $_GET['entry'] to that ID,
243	 * so that FlatPress can find it where it is expected
244	 *
245	 */
246
247	
248	function cache_init() {
249	
250		global $fp_params;
251		
252		$this->fp_params =& $fp_params;
253		$this->baseurl = PRETTYURLS_PATHINFO? BLOG_BASEURL . 'index.php/' : BLOG_BASEURL;
254	
255		if (PRETTYURLS_TITLES) {
256			#if ($f = io_load_file(PRETTYURLS_CACHE))
257			$this->index = array(); #unserialize($f);
258			
259			if (!file_exists(PRETTYURLS_CACHE))
260				$this->cache_create();
261
262
263			$this->categories(false);
264		}
265
266		
267		if (!defined('MOD_INDEX'))
268			return;
269		
270
271		# this is not working if you reach flatpress via symlink
272		# unless you don't edit manually defaults.php
273		if (strpos($_SERVER['REQUEST_URI'], BLOG_ROOT)!==false) {
274			$url = $_SERVER['REQUEST_URI'];
275			$del = BLOG_ROOT;
276			if (strpos($url, 'index.php')!==false)
277				$del = $del . 'index.php/';
278			$url = substr($url, strlen($del)-1);
279		}
280		
281		// removes querystrings
282		if (false !== $i = strpos($url, '?'))
283			$url = substr($url, 0, $i);
284
285		// removes anchors
286		if (false !== $i = strpos($url, '#'))
287			$url = substr($url, 0, $i);
288
289	
290		if (strrpos($url, '/') != (strlen($url)-1)) {
291			$url .= '/';
292		}
293
294
295		if ($url=='/')
296			return;
297
298	
299		
300		//date
301		$url = preg_replace_callback(
302			'!^/[0-9]{2}(?P<y>[0-9]{2})(/(?P<m>[0-9]{2})(/(?P<d>[0-9]{2}))?)?!', 
303			array(&$this, 'handle_date'), 
304			$url
305			);
306			
307		
308		if (!$this->date_handled){
309			// static page
310			$url = preg_replace_callback('|^/([a-zA-Z0-9_-]+)/$|', array(&$this, 'handle_static'), $url);
311			if ($this->status == 2)
312				return $this->check_url($url);
313		}
314		
315		
316		$url = preg_replace_callback('{category/([^/]+)/}', array(&$this, 'handle_categories'), $url);
317		
318		
319		$url = preg_replace_callback('|page/([0-9]+)/$|', array(&$this, 'handle_page'), $url);		
320		if ($this->status == 2)
321			return $this->check_url($url);	
322		
323		if ($this->date_handled){
324			$url = preg_replace_callback('|^/([^/]+)|', array(&$this, 'handle_entry'), $url);
325			// if status = 2
326				/*
327					utils_error(404);
328				*/
329			
330			$url = preg_replace_callback('|^/comments|', array(&$this, 'handle_comment'), $url);
331		}
332		
333		
334		$url = preg_replace_callback('|^/feed(/([^/]*))?|', array(&$this, 'handle_feed'), $url);
335		
336		$this->check_url($url);
337		
338	}
339
340	function check_url($url) {
341		if (!empty($url) && $url != '/') {
342			$this->fp_params = array('entry'=>'entry000000-000000');
343		}
344	}
345
346	function cache_delete_elem($id, $date) {
347	
348		# is this a title change?
349		if (false !== ($ids = $this->cache_get( $date['y'] ,  $date['m'] ,  $date['d'] )))
350			$hash = array_search($id, $ids);
351		else
352			return;
353		
354		if ($hash) {
355			unset($this->index[ $date['y'] ] [ $date['m'] ][ $date['d'] ][ $hash ]);
356			
357			if (empty($this->index[ $date['y'] ] [ $date['m'] ][ $date['d'] ])) {
358				unset($this->index[ $date['y'] ] [ $date['m'] ][ $date['d'] ]);
359			
360				if (empty($this->index[ $date['y'] ] [ $date['m'] ])) {
361					unset($this->index[ $date['y'] ] [ $date['m'] ]);
362			
363					if (empty($this->index[ $date['y'] ])) {
364						unset($this->index[ $date['y'] ]);
365					}
366					
367				}
368				
369			}
370			
371		}
372
373		$this->cache_save();
374	
375	}
376	
377	function cache_add($id, &$arr) {
378		
379		$date = date_from_id($id);
380		$title = sanitize_title($arr['subject']);
381		
382		$this->cache_delete_elem($id, $date);
383		
384		$this->index[ $date['y'] ] [ $date['m'] ][ $date['d'] ][ md5($title) ] = $id;
385		
386		$this->cache_save();
387	
388		
389		return true;
390		
391	}
392
393	function cache_get($y,$m,$d=null,$h=null) {
394		if (!isset($this->index[$y][$m])) {
395			$s = @io_load_file(PRETTYURLS_CACHE.$y.$m);
396			$this->index[$y][$m] = $s? unserialize($s) : false;
397		}
398
399		if (is_null($d))
400			return $this->index[$y][$m];
401
402		if (is_null($h))
403			return isset($this->index[$y][$m][$d])? $this->index[$y][$m][$d] : false;
404
405		if (isset($this->index[$y][$m][$d]))
406			return isset($this->index[$y][$m][$d][$h]);
407		else
408			return false;
409	}
410	
411	function cache_delete($id) {
412		$date = date_from_id($id);
413		$this->cache_delete_elem($id, $date);
414		$this->cache_save();
415	
416	}
417
418	function cache_save() {
419		if ($this->index) {
420			foreach ($this->index as $year => $months) {
421				foreach ($months as $month => $days)
422				io_write_file(PRETTYURLS_CACHE.$year.$month, serialize($days));
423			}
424
425		}
426		
427		return true;
428		
429	}
430
431	function nextprevlink($nextprev, $v) {
432	
433		global $fpdb;	
434		$q =& $fpdb->getQuery();
435		
436		list($caption, $id) = call_user_func(array(&$q, 'get'.$nextprev));
437	
438		if (!$id)
439			return array();
440		
441		
442		if ($q->single) {
443			$date = date_from_id($id);
444			$title = sanitize_title($caption);
445			$url = $this->baseurl  . "20{$date['y']}/{$date['m']}/{$date['d']}/$title/";
446			
447			if ($v>0) 
448				$caption = $caption . ' &raquo '; 
449			else
450				$caption = ' &laquo ' . $caption;
451			
452			return array($caption,$url);
453			
454		}
455		
456		
457		// else, we build a complete url
458		
459		/* todo: clean up this mess... which means cleaning up the mess above. oh, my! */
460		
461		$l = $this->baseurl ;
462		
463		
464		if ( ( 	is_numeric($cid = @$this->fp_params['category']) ) ||
465				is_numeric($cid = @$this->fp_params['cat']) ) 
466			$l = $this->categorylink($l, $cid);
467		
468		if (isset($this->fp_params['y']) && $this->fp_params['y']) {
469			$l .= '20'. $this->fp_params['y'] . '/';
470			
471			if (isset($this->fp_params['m']) && $this->fp_params['m']) {
472				$l .= $this->fp_params['m']  . '/';
473			
474				if (isset($this->fp_params['d']) && $this->fp_params['d'])
475					$l .= $this->fp_params['d']  . '/';
476		
477			}
478			
479		}
480		
481		$page = 1;
482		
483		if (isset($this->fp_params['paged']) && $this->fp_params['paged']>1) $page = $this->fp_params['paged'];
484	
485		$page += $v;
486		
487		if ($page > 0) {
488			$l .= 'page/' . $page . '/';
489		}
490		
491		
492		return array($caption,$l);
493		
494		
495	}
496	
497	
498	
499}	
500
501	global $plugin_prettyurls;
502	$plugin_prettyurls = new Plugin_PrettyURLs;
503	$plugin_prettyurls->categories();
504	
505	
506	if (!defined('MOD_ADMIN_PANEL')){
507	
508		if (!function_exists('get_nextpage_link')) :
509		
510		function get_nextpage_link() {
511			global $plugin_prettyurls;
512			return $plugin_prettyurls->nextprevlink('NextPage', 1);
513		}
514		function get_prevpage_link() {
515			global $plugin_prettyurls;
516			return $plugin_prettyurls->nextprevlink('PrevPage',-1);
517		}
518		
519		endif;
520		
521	}
522	
523	
524
525	add_filter('post_link', 	array(&$plugin_prettyurls,'permalink'), 0, 2);
526	add_filter('comments_link', array(&$plugin_prettyurls, 'commentlink'), 0, 2);
527	add_filter('feed_link', 	array(&$plugin_prettyurls, 'feedlink'), 0, 2);
528	add_filter('post_comments_feed_link', array(&$plugin_prettyurls, 'commentsfeedlink'), 0, 3);
529	add_filter('category_link', array(&$plugin_prettyurls,'categorylink'), 0, 2);
530	add_filter('page_link', 	array(&$plugin_prettyurls, 'staticlink'), 0, 2);
531	
532	// date related functions
533	add_filter('year_link', 	array(&$plugin_prettyurls,'yearlink'), 0, 2);
534	add_filter('month_link', 	array(&$plugin_prettyurls,'monthlink'), 0, 3);
535	add_filter('day_link', 		array(&$plugin_prettyurls,'daylink'), 0, 4);
536
537	if (PRETTYURLS_TITLES) {
538		add_filter('publish_post', 	array(&$plugin_prettyurls, 'cache_add'), 5, 2);
539		add_filter('delete_post', 	array(&$plugin_prettyurls, 'cache_delete'));
540		add_action('update_categories',  array(&$plugin_prettyurls, 'categories'));
541	}
542
543	add_filter('init', 			array(&$plugin_prettyurls, 'cache_init'));
544
545if (class_exists('AdminPanelAction')){
546
547	class admin_plugin_prettyurls extends AdminPanelAction { 
548		
549		var $langres = 'plugin:prettyurls';
550		
551		function setup() {
552			$this->smarty->assign('admin_resource', "plugin:prettyurls/admin.plugin.prettyurls");
553			$blogroot = BLOG_ROOT;
554			$f = ABS_PATH . '.htaccess';
555			$txt = io_load_file($f);
556			if (!$txt) {
557		
558$txt =<<<STR
559
560# Thanks again WP :)
561
562<IfModule mod_rewrite.c>
563RewriteEngine On
564RewriteBase {$blogroot}
565RewriteCond %{REQUEST_FILENAME} !-f
566RewriteCond %{REQUEST_FILENAME} !-d
567RewriteRule . {$blogroot}index.php [L]
568</IfModule>
569STR;
570			}
571			
572			
573			$this->smarty->assign('cantsave', 
574				( !is_writable(ABS_PATH) || (file_exists($f) && !is_writable($f)) )
575			);	
576			$this->smarty->assign('htaccess', $txt);		
577		}
578		
579		
580		
581		function onsubmit() {
582			global $fp_config;
583			
584			if (!empty($_POST['htaccess']) && io_write_file(ABS_PATH.'.htaccess', $_POST['htaccess'])){
585				$this->smarty->assign('success', 1);
586			} else {
587			 	$this->smarty->assign('success', -1);
588			}
589			
590			return 2;
591		}
592		
593	}
594
595	admin_addpanelaction('plugin', 'prettyurls', true);
596
597}
598
599?>