From c1aa6f4fbbb25b9bbe97be7572f142e0d5c500ea Mon Sep 17 00:00:00 2001
From: Shish <shish@shishnet.org>
Date: Fri, 27 Jan 2012 17:29:59 +0000
Subject: [PATCH 1/2] how did this ever work o_O

---
 contrib/oekaki/main.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/contrib/oekaki/main.php b/contrib/oekaki/main.php
index 7fda9a34..7a571242 100644
--- a/contrib/oekaki/main.php
+++ b/contrib/oekaki/main.php
@@ -83,6 +83,7 @@ class Oekaki extends SimpleExtension {
 
 	// FIXME: "edit this image" button on existing images?
 	function onPostListBuilding($event) {
+		global $user, $page;
 		if($this->can_upload($user)) {
 			$this->theme->display_block($page);
 		}

From 6e64857936cc7fbb0b7eed24bbc0e0b028fb2a00 Mon Sep 17 00:00:00 2001
From: Shish <shish@shishnet.org>
Date: Fri, 27 Jan 2012 18:16:46 +0000
Subject: [PATCH 2/2] wibble towards being totally SimpleExtension based, as
 that's easier to programatically optimise

---
 contrib/admin/main.php          |  3 +-
 contrib/artists/main.php        |  3 +-
 contrib/bookmarks/main.php      |  3 +-
 contrib/browser_search/main.php |  3 +-
 contrib/danbooru_api/main.php   |  3 +-
 contrib/downtime/main.php       |  3 +-
 contrib/handle_flash/main.php   |  1 -
 contrib/handle_mp3/main.php     |  1 -
 contrib/handle_svg/main.php     |  4 +--
 contrib/holiday/main.php        |  1 -
 contrib/ipban/main.php          |  3 +-
 contrib/link_image/main.php     |  3 +-
 contrib/numeric_score/main.php  |  3 +-
 contrib/rating/main.php         |  3 +-
 contrib/report_image/main.php   |  5 ++--
 contrib/res_limit/main.php      |  3 +-
 contrib/tag_editcloud/main.php  |  3 +-
 contrib/tag_history/main.php    |  4 ++-
 contrib/tagger/main.php         |  8 ++++--
 contrib/word_filter/main.php    |  4 ++-
 core/extension.class.php        | 50 ++++++++++++++++-----------------
 core/util.inc.php               | 15 ++++++----
 index.php                       | 24 ++++++++++++++--
 23 files changed, 95 insertions(+), 58 deletions(-)

diff --git a/contrib/admin/main.php b/contrib/admin/main.php
index e7cf5f20..c099b066 100644
--- a/contrib/admin/main.php
+++ b/contrib/admin/main.php
@@ -38,6 +38,8 @@ class AdminBuildingEvent extends Event {
 class AdminPage implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -179,5 +181,4 @@ class AdminPage implements Extension {
 	}
 	*/
 }
-add_event_listener(new AdminPage());
 ?>
diff --git a/contrib/artists/main.php b/contrib/artists/main.php
index ada1b4e5..cd9190cb 100644
--- a/contrib/artists/main.php
+++ b/contrib/artists/main.php
@@ -22,6 +22,8 @@ class AuthorSetEvent extends Event {
 class Artists implements Extension {
     var $theme;
 
+	public function get_priority() {return 50;}
+
     public function receive_event(Event $event)
     {
         global $user;
@@ -1221,5 +1223,4 @@ class Artists implements Extension {
             return $result;
 	}	
 }
-add_event_listener(new Artists());
 ?>
diff --git a/contrib/bookmarks/main.php b/contrib/bookmarks/main.php
index 9e26b85e..da86f605 100644
--- a/contrib/bookmarks/main.php
+++ b/contrib/bookmarks/main.php
@@ -9,6 +9,8 @@
 class Bookmarks implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -64,5 +66,4 @@ class Bookmarks implements Extension {
 		$database->Execute($sql, array($user->id, $url, $title));
 	}
 }
-add_event_listener(new Bookmarks());
 ?>
diff --git a/contrib/browser_search/main.php b/contrib/browser_search/main.php
index fc113121..cf5ee6ac 100755
--- a/contrib/browser_search/main.php
+++ b/contrib/browser_search/main.php
@@ -14,6 +14,8 @@
  */
 
 class BrowserSearch implements Extension {
+
+	public function get_priority() {return 50;}
 	public function receive_event(Event $event) {
 	global $page;
 	global $config;
@@ -112,5 +114,4 @@ class BrowserSearch implements Extension {
 		}
 	}
 }
-add_event_listener(new BrowserSearch());
 ?>
diff --git a/contrib/danbooru_api/main.php b/contrib/danbooru_api/main.php
index b925d860..898680f2 100644
--- a/contrib/danbooru_api/main.php
+++ b/contrib/danbooru_api/main.php
@@ -49,6 +49,8 @@ Completely compatibility will probably involve a rewrite with a different URL
 
 class DanbooruApi implements Extension
 {
+
+	public function get_priority() {return 50;}
 	// Receive the event
 	public function receive_event(Event $event)
 	{
@@ -425,5 +427,4 @@ class DanbooruApi implements Extension
 	}
 }
 
-add_event_listener(new DanbooruApi());
 ?>
diff --git a/contrib/downtime/main.php b/contrib/downtime/main.php
index 67727b31..5dc57690 100644
--- a/contrib/downtime/main.php
+++ b/contrib/downtime/main.php
@@ -14,6 +14,8 @@
 class Downtime implements Extension {
 	var $theme;
 
+	public function get_priority() {return 10;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -42,5 +44,4 @@ class Downtime implements Extension {
 		else return false;
 	}
 }
-add_event_listener(new Downtime(), 10);
 ?>
diff --git a/contrib/handle_flash/main.php b/contrib/handle_flash/main.php
index 8ee32fc0..79cfc4ff 100644
--- a/contrib/handle_flash/main.php
+++ b/contrib/handle_flash/main.php
@@ -100,5 +100,4 @@ class FlashFileHandler extends DataHandlerExtension {
 		return $bounds;
 	}
 }
-add_event_listener(new FlashFileHandler());
 ?>
diff --git a/contrib/handle_mp3/main.php b/contrib/handle_mp3/main.php
index 76187638..a4a74cfb 100644
--- a/contrib/handle_mp3/main.php
+++ b/contrib/handle_mp3/main.php
@@ -39,5 +39,4 @@ class MP3FileHandler extends DataHandlerExtension {
 		return (file_exists($file));
 	}
 }
-add_event_listener(new MP3FileHandler());
 ?>
diff --git a/contrib/handle_svg/main.php b/contrib/handle_svg/main.php
index f028e178..e2d02a3f 100644
--- a/contrib/handle_svg/main.php
+++ b/contrib/handle_svg/main.php
@@ -8,6 +8,8 @@
 class SVGFileHandler implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
 
@@ -113,6 +115,4 @@ class MiniSVGParser {
 	function endElement($parser, $name) {
 	}
 }
-
-add_event_listener(new SVGFileHandler());
 ?>
diff --git a/contrib/holiday/main.php b/contrib/holiday/main.php
index 598e2a89..aea352f8 100644
--- a/contrib/holiday/main.php
+++ b/contrib/holiday/main.php
@@ -28,6 +28,5 @@ class Holiday extends SimpleExtension {
 			}
 		}
 	}
-
 }
 ?>
diff --git a/contrib/ipban/main.php b/contrib/ipban/main.php
index cc7180b9..cb9abded 100644
--- a/contrib/ipban/main.php
+++ b/contrib/ipban/main.php
@@ -37,6 +37,8 @@ class AddIPBanEvent extends Event {
 class IPBan implements Extension {
 	var $theme;
 // event handler {{{
+	public function get_priority() {return 10;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -264,5 +266,4 @@ class IPBan implements Extension {
 	}
 // }}}
 }
-add_event_listener(new IPBan(), 10);
 ?>
diff --git a/contrib/link_image/main.php b/contrib/link_image/main.php
index 416891b9..d8773362 100644
--- a/contrib/link_image/main.php
+++ b/contrib/link_image/main.php
@@ -7,6 +7,8 @@
 class LinkImage implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -48,5 +50,4 @@ class LinkImage implements Extension {
 			'text_link' => $text_link);
 	}
 }
-add_event_listener(new LinkImage());
 ?>
diff --git a/contrib/numeric_score/main.php b/contrib/numeric_score/main.php
index e07b1a9d..963953d9 100644
--- a/contrib/numeric_score/main.php
+++ b/contrib/numeric_score/main.php
@@ -22,6 +22,8 @@ class NumericScoreSetEvent extends Event {
 class NumericScore implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -271,5 +273,4 @@ class NumericScore implements Extension {
 			array($image_id, $image_id));
 	}
 }
-add_event_listener(new NumericScore());
 ?>
diff --git a/contrib/rating/main.php b/contrib/rating/main.php
index 52f71f7a..f6855e79 100644
--- a/contrib/rating/main.php
+++ b/contrib/rating/main.php
@@ -20,6 +20,8 @@ class RatingSetEvent extends Event {
 class Ratings implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -218,5 +220,4 @@ class Ratings implements Extension {
 		}
 	}
 }
-add_event_listener(new Ratings());
 ?>
diff --git a/contrib/report_image/main.php b/contrib/report_image/main.php
index e5b2c589..970be8d7 100755
--- a/contrib/report_image/main.php
+++ b/contrib/report_image/main.php
@@ -32,6 +32,8 @@ class AddReportedImageEvent extends Event {
 class ReportImage implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -143,8 +145,6 @@ class ReportImage implements Extension {
 		return $reports;
 	}
 }
-add_event_listener(new ReportImage(), 29); // Not sure what I'm in before.
-
 //  ===== Changelog =====
 // * Version 0.3a / 0.3a_rc - 11/06/07 - I can no longer use the same theme.php file for both SVN and RCx. Sorry.
 // *   Same deal with theme.php as it is with main.php
@@ -154,5 +154,4 @@ add_event_listener(new ReportImage(), 29); // Not sure what I'm in before.
 // * Version 0.2b - 10/27/07 - Now supports Shimmie2 RC2!
 // * Version 0.2a - 10/24/07 - Fixed some SQL issues. I will make sure to test before commiting :)
 // * Version 0.2 - 10/24/07 - First public release.
-
 ?>
diff --git a/contrib/res_limit/main.php b/contrib/res_limit/main.php
index f6214ab4..d8ff1dc0 100644
--- a/contrib/res_limit/main.php
+++ b/contrib/res_limit/main.php
@@ -6,6 +6,8 @@
  * Description: Allows the admin to set min / max image dimentions
  */
 class ResolutionLimit implements Extension {
+	public function get_priority() {return 40;} // early, to veto ImageUploadEvent
+
 	public function receive_event(Event $event) {
 		if($event instanceof ImageAdditionEvent) {
 			global $config;
@@ -68,5 +70,4 @@ class ResolutionLimit implements Extension {
 		}
 	}
 }
-add_event_listener(new ResolutionLimit(), 40); // early, to veto UIE
 ?>
diff --git a/contrib/tag_editcloud/main.php b/contrib/tag_editcloud/main.php
index 85bdc8b4..a6b9ecf0 100644
--- a/contrib/tag_editcloud/main.php
+++ b/contrib/tag_editcloud/main.php
@@ -15,6 +15,8 @@
 class TagEditCloud implements Extension {
         var $theme;
 
+	public function get_priority() {return 50;}
+
         public function receive_event(Event $event) {
                 global $config, $database, $page, $user;
                 //if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -133,5 +135,4 @@ class TagEditCloud implements Extension {
 	}
 
 }
-add_event_listener(new TagEditCloud());
 ?>
diff --git a/contrib/tag_history/main.php b/contrib/tag_history/main.php
index d6f00845..017c056d 100644
--- a/contrib/tag_history/main.php
+++ b/contrib/tag_history/main.php
@@ -8,6 +8,9 @@
 class Tag_History implements Extension {
 	var $theme;
 
+	// in before tags are actually set, so that "get current tags" works
+	public function get_priority() {return 40;}
+
 	public function receive_event(Event $event) {
 		global $config, $database, $page, $user;
 		if(is_null($this->theme)) $this->theme = get_theme_object($this);
@@ -350,5 +353,4 @@ class Tag_History implements Extension {
 		}
 	}
 }
-add_event_listener(new Tag_History(), 40); // in before tags are actually set, so that "get current tags" works
 ?>
diff --git a/contrib/tagger/main.php b/contrib/tagger/main.php
index f572889c..547f9ebc 100644
--- a/contrib/tagger/main.php
+++ b/contrib/tagger/main.php
@@ -9,6 +9,8 @@
 class Tagger implements Extension {
 	var $theme;
 
+	public function get_priority() {return 50;}
+
 	public function receive_event(Event $event) {
 		if(is_null($this->theme))
 			$this->theme = get_theme_object($this);
@@ -38,10 +40,10 @@ class Tagger implements Extension {
 	}
 }
 
-add_event_listener(new Tagger());
-
 // Tagger AJAX back-end
 class TaggerXML implements Extension {
+	public function get_priority() {return 10;}
+
 	public function receive_event(Event $event) {
 		if(($event instanceof PageRequestEvent) && $event->page_matches("tagger/tags")) {
 			global $page;
@@ -170,5 +172,5 @@ class TaggerXML implements Extension {
 
 		return $list;
 	}
-} add_event_listener( new taggerXML(),10);
+} 
 ?>
diff --git a/contrib/word_filter/main.php b/contrib/word_filter/main.php
index d3c58293..5e4cddd2 100644
--- a/contrib/word_filter/main.php
+++ b/contrib/word_filter/main.php
@@ -7,6 +7,9 @@
  */
 
 class WordFilter implements Extension {
+	// before emoticon filter
+	public function get_priority() {return 40;}
+
 	public function receive_event(Event $event) {
 		if($event instanceof TextFormattingEvent) {
 			$event->formatted = $this->filter($event->formatted);
@@ -45,5 +48,4 @@ class WordFilter implements Extension {
 		return $map;
 	}
 }
-add_event_listener(new WordFilter(), 40); // before emoticon filter
 ?>
diff --git a/core/extension.class.php b/core/extension.class.php
index ccd287d2..e02df376 100644
--- a/core/extension.class.php
+++ b/core/extension.class.php
@@ -67,6 +67,7 @@
  */
 interface Extension {
 	public function receive_event(Event $event);
+	public function get_priority();
 }
 
 /**
@@ -105,18 +106,18 @@ abstract class SimpleExtension implements Extension {
 		}
 	}
 
-	public function get_priority() {return 50;}
+	public function get_priority() {
+		return 50;
+	}
 }
 
 /**
  * Several extensions have this in common, make a common API
  */
-abstract class FormatterExtension implements Extension {
-	public function receive_event(Event $event) {
-		if($event instanceof TextFormattingEvent) {
-			$event->formatted = $this->format($event->formatted);
-			$event->stripped  = $this->strip($event->stripped);
-		}
+abstract class FormatterExtension extends SimpleExtension {
+	public function onTextFormatting($event) {
+		$event->formatted = $this->format($event->formatted);
+		$event->stripped  = $this->strip($event->stripped);
 	}
 
 	abstract public function format($text);
@@ -127,20 +128,14 @@ abstract class FormatterExtension implements Extension {
  * This too is a common class of extension with many methods in common,
  * so we have a base class to extend from
  */
-abstract class DataHandlerExtension implements Extension {
-	var $theme;
-
-	public function receive_event(Event $event) {
-		if(is_null($this->theme)) $this->theme = get_theme_object($this);
-
-		if(($event instanceof DataUploadEvent) && $this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
-		
+abstract class DataHandlerExtension extends SimpleExtension {
+	public function onDataUpload($event) {
+		if($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
 			if(!move_upload_to_archive($event)) return;
 			send_event(new ThumbnailGenerationEvent($event->hash, $event->type));
 
 			/* Check if we are replacing an image */
-			if (array_key_exists('replace',$event->metadata) && isset($event->metadata['replace']))
-			{
+			if(array_key_exists('replace', $event->metadata) && isset($event->metadata['replace'])) {
 				/* hax: This seems like such a dirty way to do this.. */
 				
 				/* Validate things */
@@ -168,8 +163,7 @@ abstract class DataHandlerExtension implements Extension {
 				send_event($ire);
 				$event->image_id = $image_id;
 			}
-			else
-			{
+			else {
 				$image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata);
 				if(is_null($image)) {
 					throw new UploadException("Data handler failed to create image object from data");
@@ -192,8 +186,10 @@ abstract class DataHandlerExtension implements Extension {
 				}
 			}
 		}
+	}
 
-		if(($event instanceof ThumbnailGenerationEvent) && $this->supported_ext($event->type)) {
+	public function onThumnbnailGeneration($event) {
+		if($this->supported_ext($event->type)) {
 			if (method_exists($this, 'create_thumb_force') && $event->force == true) {
 				 $this->create_thumb_force($event->hash);
 			}
@@ -201,16 +197,18 @@ abstract class DataHandlerExtension implements Extension {
 				$this->create_thumb($event->hash);
 			}
 		}
+	}
 
-		if(($event instanceof DisplayingImageEvent) && $this->supported_ext($event->image->ext)) {
-			global $page;
+	public function onDisplayingImage($event) {
+		global $page;
+		if($this->supported_ext($event->image->ext)) {
 			$this->theme->display_image($page, $event->image);
 		}
+	}
 
-		if(($event instanceof SetupBuildingEvent)) {
-			$sb = $this->setup();
-			if($sb) $event->panel->add_block($sb);
-		}
+	public function onSetupBuilding($event) {
+		$sb = $this->setup();
+		if($sb) $event->panel->add_block($sb);
 	}
 
 	protected function setup() {}
diff --git a/core/util.inc.php b/core/util.inc.php
index f87ad268..7005d840 100644
--- a/core/util.inc.php
+++ b/core/util.inc.php
@@ -790,12 +790,14 @@ $_event_listeners = array();
 /**
  * Register an Extension
  */
-function add_event_listener(Extension $extension, $pos=50) {
+function add_event_listener(Extension $extension, $pos=50, $events=array()) {
 	global $_event_listeners;
-	while(isset($_event_listeners[$pos])) {
-		$pos++;
+	foreach($events as $event) {
+		while(isset($_event_listeners[$event][$pos])) {
+			$pos++;
+		}
+		$_event_listeners[$event][$pos] = $extension;
 	}
-	$_event_listeners[$pos] = $extension;
 }
 
 /** @private */
@@ -806,8 +808,11 @@ $_event_count = 0;
  */
 function send_event(Event $event) {
 	global $_event_listeners, $_event_count;
+	if(!isset($_event_listeners[get_class($event)])) return;
+
 	ctx_log_start(get_class($event));
-	$my_event_listeners = $_event_listeners; // http://bugs.php.net/bug.php?id=35106
+	// SHIT: http://bugs.php.net/bug.php?id=35106
+	$my_event_listeners = $_event_listeners[get_class($event)];
 	ksort($my_event_listeners);
 	foreach($my_event_listeners as $listener) {
 		ctx_log_start(get_class($listener));
diff --git a/index.php b/index.php
index 25e363c3..226be790 100644
--- a/index.php
+++ b/index.php
@@ -138,11 +138,31 @@ try {
 
 
 	// initialise the extensions
+	$all_events = array();
 	foreach(get_declared_classes() as $class) {
-		if(is_subclass_of($class, "SimpleExtension")) {
+		if(is_subclass_of($class, "Event")) {
+			$all_events[] = $class;
+		}
+	}
+	foreach(get_declared_classes() as $class) {
+		$rclass = new ReflectionClass($class);
+		if($rclass->isAbstract()) {
+			// don't do anything
+		}
+		elseif(is_subclass_of($class, "SimpleExtension")) {
 			$c = new $class();
 			$c->i_am($c);
-			add_event_listener($c, $c->get_priority());
+			$my_events = array();
+			foreach(get_class_methods($c) as $method) {
+				if(substr($method, 0, 2) == "on") {
+					$my_events[] = substr($method, 2) . "Event";
+				}
+			}
+			add_event_listener($c, $c->get_priority(), $my_events);
+		}
+		elseif(is_subclass_of($class, "Extension")) {
+			$c = new $class();
+			add_event_listener($c, $c->get_priority(), $all_events);
 		}
 	}
 	ctx_log_endok("Initialisation");