00001 <?php
00007 namespace Habari;
00008
00012 class RewriteRules extends \ArrayObject
00013 {
00014
00015 protected static $sorted_rules_cache = null;
00016
00023 public static function add_system_rules( $rules )
00024 {
00025 $default_rules = array(
00026
00027 array( 'name' => 'display_home', 'parse_regex' => '#^(?:page/(?P<page>0|1))?/?$#', 'build_str' => '(page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_home', 'priority' => 1000, 'description' => 'Homepage (index) display' ),
00028 array( 'name' => 'display_entries', 'parse_regex' => '#^(?:page/(?P<page>[2-9]|[1-9][0-9]+))/?$#', 'build_str' => '(page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_entries', 'priority' => 999, 'description' => 'Display multiple entries' ),
00029 array( 'name' => 'display_entries_by_date', 'parse_regex' => '#^(?P<year>[1,2]{1}[\d]{3})(?:/(?P<month>[\d]{2}))?(?:/(?P<day>[\d]{2}))?(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$year}(/{$month})(/{$day})(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_date', 'priority' => 2, 'description' => 'Displays posts for a specific date.' ),
00030 array( 'name' => 'display_entries_by_tag', 'parse_regex' => '#^tag/(?P<tag>[^/]*)(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => 'tag/{$tag}(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_tag', 'priority' => 5, 'description' => 'Return posts matching specified tag.', 'parameters' => serialize( array( 'require_match' => Method::create('\\Habari\\Tag', 'rewrite_tag_exists') ) ) ),
00031 array( 'name' => 'display_entry', 'parse_regex' => '#^(?P<slug>[^/]+)(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$slug}(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_post', 'priority' => 100, 'description' => 'Return entry matching specified slug', 'parameters' => serialize( array( 'require_match' => Method::create('\\Habari\\Posts', 'rewrite_match_type'), 'content_type'=>'entry', 'request_types' => array('display_post') ) ) ),
00032 array( 'name' => 'display_page', 'parse_regex' => '#^(?P<slug>[^/]+)(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$slug}(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_post', 'priority' => 100, 'description' => 'Return page matching specified slug', 'parameters' => serialize( array( 'require_match' => Method::create('\\Habari\\Posts', 'rewrite_match_type'), 'content_type'=>'page', 'request_types' => array('display_post') ) ) ),
00033 array( 'name' => 'display_search', 'parse_regex' => '#^search(?:/(?P<criteria>[^/]+))?(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => 'search(/{$criteria})(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'search', 'priority' => 8, 'description' => 'Searches posts' ),
00034 array( 'name' => 'display_404', 'parse_regex' => '/^.*$/', 'build_str' => '', 'handler' => 'UserThemeHandler', 'action' => 'display_404', 'priority' => 9999, 'description' => 'Displays an error page when a URL is not matched.' ),
00035 array( 'name' => 'display_post', 'parse_regex' => '#^(?P<slug>[^/]+)(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$slug}(/page/{$page})', 'handler' => 'UserThemeHandler', 'action' => 'display_post', 'priority' => 9998, 'description' => 'Fallback to return post matching specified slug if no content_type match' ),
00036
00037
00038 array( 'name' => 'submit_feedback', 'parse_regex' => '#^(?P<id>[0-9]+)/feedback/?$#i', 'build_str' => '{$id}/feedback', 'handler' => 'FeedbackHandler', 'action' => 'add_comment', 'priority' => 8, 'description' => 'Adds a comment to a post' ),
00039
00040
00041 array( 'name' => 'display_dashboard', 'parse_regex' => '#^admin/?$#', 'build_str' => 'admin', 'handler' => 'AdminDashboardHandler', 'action' => 'dashboard', 'priority' => 4, 'description' => 'Display the admin dashboard' ),
00042 array( 'name' => 'display_publish', 'parse_regex' => '#^admin/publish/(?P<content_type_name>[^/]+)(?:/(?P<id>.+))?/?$#', 'build_str' => 'admin/publish/{$content_type_name}(/{$id})', 'handler' => 'AdminPostsHandler', 'action' => 'publish', 'priority' => 4, 'description' => 'Manage publishing posts' ),
00043 array( 'name' => 'display_posts', 'parse_regex' => '#^admin/posts/?$#', 'build_str' => 'admin/posts', 'handler' => 'AdminPostsHandler', 'action' => 'posts', 'priority' => 4, 'description' => 'Manage posts' ),
00044 array( 'name' => 'delete_post', 'parse_regex' => '#^admin/delete_post/?$#', 'build_str' => 'admin/delete_post', 'handler' => 'AdminPostsHandler', 'action' => 'delete_post', 'priority' => 4, 'description' => 'Delete a post' ),
00045 array( 'name' => 'user_profile', 'parse_regex' => '#^admin/user/(?P<user>[^/]+)/?$#', 'build_str' => 'admin/user/{$user}', 'handler' => 'AdminUsersHandler', 'action' => 'user', 'priority' => 4, 'description' => 'The profile page for a specific user' ),
00046 array( 'name' => 'display_users', 'parse_regex' => '#^admin/users/?$#', 'build_str' => 'admin/users', 'handler' => 'AdminUsersHandler', 'action' => 'users', 'priority' => 4, 'description' => 'Manage users' ),
00047 array( 'name' => 'own_user_profile', 'parse_regex' => '#^admin/user/?$#', 'build_str' => 'admin/user', 'handler' => 'AdminUsersHandler', 'action' => 'user', 'priority' => 4, 'description' => 'The profile page for a specific user' ),
00048 array( 'name' => 'display_themes', 'parse_regex' => '#^admin/themes/?$#', 'build_str' => 'admin/themes', 'handler' => 'AdminThemesHandler', 'action' => 'themes', 'priority' => 4, 'description' => 'Manage themes' ),
00049 array( 'name' => 'activate_theme', 'parse_regex' => '#^admin/activate_theme/?$#', 'build_str' => 'admin/activate_theme', 'handler' => 'AdminThemesHandler', 'action' => 'activate_theme', 'priority' => 4, 'description' => 'Activate a theme' ),
00050 array( 'name' => 'preview_theme', 'parse_regex' => '#^admin/preview_theme/?$#', 'build_str' => 'admin/preview_theme', 'handler' => 'AdminThemesHandler', 'action' => 'preview_theme', 'priority' => 4, 'description' => 'Preview a theme' ),
00051 array( 'name' => 'configure_block', 'parse_regex' => '#^admin/configure_block/?$#i', 'build_str' => 'admin/configure_block', 'handler' => 'AdminThemesHandler', 'action' => 'configure_block', 'priority' => 4, 'description' => 'Configure a block in an iframe' ),
00052 array( 'name' => 'display_plugins', 'parse_regex' => '#^admin/plugins(?:/(?P<configure>[0-9a-f]{8})/(?P<action>.+))?/?$#', 'build_str' => 'admin/plugins(/{$configure}/{$action})', 'handler' => 'AdminPluginsHandler', 'action' => 'plugins', 'priority' => 4, 'description' => 'Manage plugins' ),
00053 array( 'name' => 'plugin_toggle', 'parse_regex' => '#^admin/plugin_toggle/?$#', 'build_str' => 'admin/plugin_toggle', 'handler' => 'AdminPluginsHandler', 'action' => 'plugin_toggle', 'priority' => 4, 'description' => 'Activate or deactivate a plugin' ),
00054 array( 'name' => 'display_options', 'parse_regex' => '#^admin/options/?$#', 'build_str' => 'admin/options', 'handler' => 'AdminOptionsHandler', 'action' => 'options', 'priority' => 4, 'description' => 'The options page for the blog' ),
00055 array( 'name' => 'display_comments', 'parse_regex' => '#^admin/comments/?$#', 'build_str' => 'admin/comments', 'handler' => 'AdminCommentsHandler', 'action' => 'comments', 'priority' => 4, 'description' => 'Manage comments' ),
00056 array( 'name' => 'edit_comment', 'parse_regex' => '#^admin/comment/(?P<id>[0-9]+)/?$#i', 'build_str' => 'admin/comment/{$id}', 'handler' => 'AdminCommentsHandler', 'action' => 'comment', 'priority' => 4, 'description' => 'Edit a comment' ),
00057 array( 'name' => 'display_groups', 'parse_regex' => '#^admin/groups/?$#', 'build_str' => 'admin/groups', 'handler' => 'AdminGroupsHandler', 'action' => 'groups', 'priority' => 4, 'description' => 'Manage groups' ),
00058 array( 'name' => 'display_group', 'parse_regex' => '#^admin/group/(?P<id>[0-9]+)/?$#i', 'build_str' => 'admin/group/{$id}', 'handler' => 'AdminGroupsHandler', 'action' => 'group', 'priority' => 4, 'description' => 'Manage a group' ),
00059 array( 'name' => 'display_tags', 'parse_regex' => '#^admin/tags/?$#i', 'build_str' => 'admin/tags', 'handler' => 'AdminTagsHandler', 'action' => 'tags', 'priority' => 4, 'description' => 'Manage tags' ),
00060 array( 'name' => 'display_logs', 'parse_regex' => '#^admin/logs/?$#i', 'build_str' => 'admin/logs', 'handler' => 'AdminLogsHandler', 'action' => 'logs', 'priority' => 4, 'description' => 'Manage logs' ),
00061 array( 'name' => 'display_import', 'parse_regex' => '#^admin/import/?$#i', 'build_str' => 'admin/import', 'handler' => 'AdminImportHandler', 'action' => 'import', 'priority' => 4, 'description' => 'Manage importing content' ),
00062 array( 'name' => 'get_locale', 'parse_regex' => '#^admin/locale/?$#i', 'build_str' => 'admin/locale', 'handler' => 'AdminLocaleHandler', 'action' => 'locale', 'priority' => 4, 'description' => 'Fetch the locale data as javascript' ),
00063 array( 'name' => 'display_sysinfo', 'parse_regex' => '#^admin/sysinfo/?$#i', 'build_str' => 'admin/sysinfo', 'handler' => 'AdminHandler', 'action' => 'sysinfo', 'priority' => 4, 'description' => 'Display system info' ),
00064
00065 array( 'name' => 'admin', 'parse_regex' => '#^admin(?:/?$|/(?P<page>[^/]*))/?$#i', 'build_str' => 'admin/({$page})', 'handler' => 'AdminHandler', 'action' => 'admin', 'priority' => 6, 'description' => 'An admin action' ),
00066
00067
00068 array( 'name' => 'admin_ajax_dashboard', 'parse_regex' => '#^admin_ajax/(?P<context>dashboard)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminDashboardHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for the admin dashboard' ),
00069 array( 'name' => 'admin_ajax_posts', 'parse_regex' => '#^admin_ajax/(?P<context>posts)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminPostsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for the managing posts' ),
00070 array( 'name' => 'admin_ajax_update_posts', 'parse_regex' => '#^admin_ajax/(?P<context>update_posts)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminPostsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for the updating posts' ),
00071 array( 'name' => 'admin_ajax_media', 'parse_regex' => '#^admin_ajax/(?P<context>media)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminPostsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling from media silos' ),
00072 array( 'name' => 'admin_ajax_media_panel', 'parse_regex' => '#^admin_ajax/(?P<context>media_panel)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminPostsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling from media panels' ),
00073 array( 'name' => 'admin_ajax_media_upload', 'parse_regex' => '#^admin_ajax/(?P<context>media_upload)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminPostsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling from media panel uploads' ),
00074 array( 'name' => 'admin_ajax_add_block', 'parse_regex' => '#^admin_ajax/(?P<context>add_block)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminThemesHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for adding a block', 'parameters' => serialize( array( 'require_permission' => array('manage_theme_config' => true) ) ) ),
00075 array( 'name' => 'admin_ajax_delete_block', 'parse_regex' => '#^admin_ajax/(?P<context>delete_block)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminThemesHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for deleting a block' ),
00076 array( 'name' => 'admin_ajax_save_areas', 'parse_regex' => '#^admin_ajax/(?P<context>save_areas)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminThemesHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for saving areas' ),
00077 array( 'name' => 'admin_ajax_comments', 'parse_regex' => '#^admin_ajax/(?P<context>comments)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminCommentsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for managing comments' ),
00078 array( 'name' => 'admin_ajax_update_comment', 'parse_regex' => '#^admin_ajax/(?P<context>update_comment)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminCommentsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for updating a comment' ),
00079 array( 'name' => 'admin_ajax_groups', 'parse_regex' => '#^admin_ajax/(?P<context>groups)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminGroupsHandler', 'action' => 'admin_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling for managing groups' ),
00080 array( 'name' => 'admin_ajax_update_groups', 'parse_regex' => '#^admin_ajax/(?P<context>update_groups)/?$#', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminGroupsHandler', 'action' => 'admin_ajax', 'priority' => 4, 'description' => 'Authenticated ajax handler for updating a group' ),
00081 array( 'name' => 'admin_ajax_tags', 'parse_regex' => '#^admin_ajax/(?P<context>tags)/?$#', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminTagsHandler', 'action' => 'admin_ajax', 'priority' => 4, 'description' => 'Authenticated ajax handler for managing tags' ),
00082 array( 'name' => 'admin_ajax_get_tags', 'parse_regex' => '#^admin_ajax/(?P<context>get_tags)/?$#', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminTagsHandler', 'action' => 'admin_ajax', 'priority' => 4, 'description' => 'Authenticated ajax handler for retrieving tags' ),
00083 array( 'name' => 'admin_ajax_logs', 'parse_regex' => '#^admin_ajax/(?P<context>logs)/?$#', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminLogsHandler', 'action' => 'admin_ajax', 'priority' => 4, 'description' => 'Authenticated ajax handler for managing logs' ),
00084 array( 'name' => 'admin_ajax_delete_logs', 'parse_regex' => '#^admin_ajax/(?P<context>delete_logs)/?$#', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminLogsHandler', 'action' => 'admin_ajax', 'priority' => 4, 'description' => 'Authenticated ajax handler for deleting logs' ),
00085
00086 array( 'name' => 'admin_ajax', 'parse_regex' => '#^admin_ajax/(?P<context>[^/]+)/?$#i', 'build_str' => 'admin_ajax/{$context}', 'handler' => 'AdminHandler', 'action' => 'admin_ajax', 'priority' => 10, 'description' => 'Authenticated ajax handling for the admin' ),
00087
00088
00089 array( 'name' => 'auth', 'parse_regex' => '#^auth/(?P<page>[^/]*)$#i', 'build_str' => 'auth/{$page}', 'handler' => 'UserHandler', 'action' => '{$page}', 'priority' => 7, 'description' => 'A user action or display, for instance the login screen' ),
00090
00091
00092 array( 'name' => 'ajax', 'parse_regex' => '#^ajax/(?P<context>[^/]+)/?$#i', 'build_str' => 'ajax/{$context}', 'handler' => 'AjaxHandler', 'action' => 'ajax', 'priority' => 8, 'description' => 'Ajax handling' ),
00093 array( 'name' => 'auth_ajax', 'parse_regex' => '#^auth_ajax/(?P<context>[^/]+)/?$#i', 'build_str' => 'auth_ajax/{$context}', 'handler' => 'AjaxHandler', 'action' => 'auth_ajax', 'priority' => 8, 'description' => 'Authenticated ajax handling' ),
00094
00095
00096 array( 'name' => 'rsd', 'parse_regex' => '/^rsd$/i', 'build_str' => 'rsd', 'handler' => 'AtomHandler', 'action' => 'rsd', 'priority' => 1, 'description' => 'RSD output' ),
00097 array( 'name' => 'atom_entry', 'parse_regex' => '#^(?P<slug>[^/]+)/atom/?$#i', 'build_str' => '{$slug}/atom', 'handler' => 'AtomHandler', 'action' => 'entry', 'priority' => 8, 'description' => 'Atom Publishing Protocol' ),
00098 array( 'name' => 'atom_feed', 'parse_regex' => '#^atom/(?P<index>[^/]+)(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => 'atom/{$index}(/page/{$page})', 'handler' => 'AtomHandler', 'action' => 'collection', 'priority' => 8, 'description' => 'Atom collection' ),
00099 array( 'name' => 'atom_feed_comments', 'parse_regex' => '#^atom/comments(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => 'atom/comments(/page/{$page})', 'handler' => 'AtomHandler', 'action' => 'comments', 'priority' => 7, 'description' => 'Entries comments' ),
00100 array( 'name' => 'atom_feed_tag', 'parse_regex' => '#^tag/(?P<tag>[^/]+)/atom(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => 'tag/{$tag}/atom(/page/{$page})', 'handler' => 'AtomHandler', 'action' => 'tag_collection', 'priority' => 8, 'description' => 'Atom Tag Collection', 'parameters' => serialize( array( 'require_match' => Method::create('\\Habari\\Tag', 'rewrite_tag_exists') ) ) ),
00101 array( 'name' => 'atom_feed_entry_comments', 'parse_regex' => '#^(?P<slug>[^/]+)/atom/comments(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$slug}/atom/comments(/page/{$page})', 'handler' => 'AtomHandler', 'action' => 'entry_comments', 'priority' => 8, 'description' => 'Entry comments' ),
00102 array( 'name' => 'atom_feed_page_comments', 'parse_regex' => '#^(?P<slug>[^/]+)/atom/comments(?:/page/(?P<page>\d+))?/?$#i', 'build_str' => '{$slug}/atom/comments(/page/{$page})', 'handler' => 'AtomHandler', 'action' => 'entry_comments', 'priority' => 8, 'description' => 'Page comments' ),
00103
00104
00105 array( 'name' => 'atompub_servicedocument', 'parse_regex' => '/^atom$/i', 'build_str' => 'atom', 'handler' => 'AtomHandler', 'action' => 'introspection', 'priority' => 1, 'description' => 'Atom introspection' ),
00106
00107
00108 array( 'name' => 'cron', 'parse_regex' => '#^cron/(?P<time>[0-9.]+)/?$#i', 'build_str' => 'cron/{$time}', 'handler' => 'CronHandler', 'action' => 'poll_cron', 'priority' => 1, 'description' => 'Asyncronous cron processing' ),
00109
00110
00111 array( 'name' => 'xmlrpc', 'parse_regex' => '#^xmlrpc/?$#i', 'build_str' => 'xmlrpc', 'handler' => 'XMLRPCServer', 'action' => 'xmlrpc_call', 'priority' => 8, 'description' => 'Handle incoming XMLRPC requests.' ),
00112 );
00113 $default_rules = Plugins::filter( 'default_rewrite_rules', $default_rules );
00114 $default_rules_properties = array( 'is_active' => 1, 'rule_class' => RewriteRule::RULE_SYSTEM );
00115 $rule_names = array_flip( Utils::array_map_field($rules, 'name') );
00116 foreach ( $default_rules as $default_rule ) {
00117 if ( !isset( $rule_names[$default_rule['name']] ) ) {
00118 $rule_properties = array_merge( $default_rule, $default_rules_properties );
00119 $rules[] = new RewriteRule( $rule_properties );
00120 }
00121 }
00122 return $rules;
00123 }
00124
00130 public static function get_active()
00131 {
00132 static $system_rules;
00133
00134 if ( !isset( $system_rules ) ) {
00135 $sql = "
00136 SELECT rr.rule_id, rr.name, rr.parse_regex, rr.build_str, rr.handler, rr.action, rr.priority, rr.parameters
00137 FROM {rewrite_rules} AS rr
00138 WHERE rr.is_active= 1
00139 ORDER BY rr.priority";
00140 $db_rules = DB::get_results( $sql, array(), '\Habari\RewriteRule' );
00141
00142 $system_rules = self::add_system_rules( $db_rules );
00143 }
00144 $rewrite_rules = Plugins::filter( 'rewrite_rules', $system_rules );
00145
00146 $rewrite_rules = self::sort_rules( $rewrite_rules );
00147
00148
00149 $c = __CLASS__;
00150 self::$sorted_rules_cache = new $c ( $rewrite_rules );
00151 return self::$sorted_rules_cache;
00152 }
00153
00164 public static function sort_rules( $rewrite_rules )
00165 {
00166 $pr = array();
00167 $max_priority = 0;
00168 foreach ( $rewrite_rules as $r ) {
00169 $priority = $r->priority;
00170 $pr[$priority][] = $r;
00171 $max_priority = max( $max_priority, $priority );
00172 }
00173 $rewrite_rules = array();
00174 for ( $z = 0; $z <= $max_priority; $z++ ) {
00175 if ( isset( $pr[$z] ) ) {
00176 $rewrite_rules = array_merge( $rewrite_rules, $pr[$z] );
00177 }
00178 }
00179 return $rewrite_rules;
00180 }
00181
00188 public static function by_name( $name )
00189 {
00190 static $named = null;
00191
00192 if ( self::$sorted_rules_cache == null ) {
00193 self::get_active();
00194 }
00195
00196 if ( $named == null ) {
00197 $named = array();
00198 $rules = self::$sorted_rules_cache;
00199 foreach ( $rules as $rule ) {
00200 $named[$rule->name][] = $rule;
00201 }
00202 }
00203
00204 return isset( $named[$name] ) ? $named[$name] : false;
00205 }
00206 }
00207
00208 ?>