^_^ The brilliance of an abstract class in this method, is that if it really is to limiting... You can simply cast it off and use the older lower level methods of doing everything.
But the idea here is to use it as a form of Identity, and cut off anything that limits our ability to delegate handling of extensions to internal functions and code which have scope issues.
Another part I forgot to mention, was how you'd be setting up extensions in LocalSettings.php. Obviously with this new method all these long ugly require_once type things is something we don't want.
So, in comes something else. I originally thought of using a function like include_extension, however there are issues with when things are loaded. ^_^ So in comes another global... (:/ Really, we use globals to much... Why not go real OOP put it all inside of a configuration instance and pass that around... Theoretically like that you could even run two instances of MediaWiki during the same request... ;) Can anyone get the hint on how that could be used to pass data from one wiki to another easier; heh, but thats a tangent) something like $wgUseExtensions and to complement it $wgExtensionPaths.
Quite simply the idea was, and you'll see why I say was in a second... that you would add extensions like this: $wgUseExtensions[] = 'CheckUser';
Then the internal code would search for CheckUser/CheckUser.php or CheckUser/CheckUser.setup.php or whatever naming convention we chose for these objects. (Probably best to come up with a different name so that things don't break by loading an old extension in a bad way). Where does it search for them? In the $wgExtensionPaths which defaults to array( "$IP/extensions" ); and because it's an array rather than something singular we still support loading extensions from alternate locations on the system.
^_^ Now for that "was"... Remember that $wgUseExtensions, and how we need to set configuration. The configuration is part of the object, to be specific it's part of an instance. Why not simplify configuration of an extension like this: $wgUseExtensions['WikiVid'] = array( 'ServiceTags' => true ); Which for my WikiVid extension would be the same as the old method of: require_once( "$IP/extensions/wiki-tools/WikiVid/WikiVid.php" ); $wgWikiVidServiceTags = true;
And also, if you later don't want something: $wgUseExtensions['WikiVid'] = false; To remove the extension from the list (before it actually gets loaded though, otherwise that's pointless).
Or if there is no configuration for it: $wgUseExtensions['ParserFunctions'] = true;
Hmmm, so you're using Smarty in MediaWiki? How far did you compare template engines? The Skin system was something we discussed in #mediawiki as something which could use some rewriting. Quite simply Skins aren't meant to be made in PHP. All this performance is nice, but there are issues when your Web Designers need to know how to write PHP to be able to create a skin in HTML. Additionally the actual inclusion of the various styles and scripts could probably use some simplification in order to make updates to what we include more portable.
~Daniel Friesen(Dantman) of: -The Gaiapedia (http://gaia.wikia.com) -Wikia ACG on Wikia.com (http://wikia.com/wiki/Wikia_ACG) -and Wiki-Tools.com (http://wiki-tools.com)
Sergey Chernyshev wrote:
Yeh, I was actually surprised that there were no abstract classes to base extensions on, but this might actually be good if flexibility is needed - we don't know what people would want to extend and at some level using abstract class might reduce possibilities, although it this class is not mandatory, then it's a good help for new developers.
I think starting with some code that people can reuse might be a good first step to identifying the right structure of classes, although I have quite little experience in extension development and there might be a good approach that'll cover most of the cases.
With widgets (which I probably should announce with separate email with thorough description) the idea was to separate the task of backend development and front-end development since vast majority of widgets are just some chunk of HTML and JS. There are still several tasks that backend needs to do, but they all standardized and Smarty is doing most of the work (I had very little idea about various templating frameworks and it was the only one with some authority).
Sergey
On Sun, May 11, 2008 at 5:57 AM, DanTMan dan_the_man@telus.net wrote:
Your idea on widgets is actually a bit similar to something I was thinking about earlier on today.
There are a lot of extensions which do similar things. And a lot of things which have a lot of variance to them. Then there is a fair bit of variance to how certain things are done and handled with extensions. Honestly, some of this makes the idea of a 'Extension Installer' that people propose to be a little tough.
For example, variables are used allot in extension files. However, most of the time none of these are globalized. As a result of this, it is impossible to delegate the inclusion of an extension to a special function made to simplify the task. So, instead we make the one installing the wiki use a cryptic require_once statement. And delegate everything being done to the extension itself forcing it to handle everything. I did entertain the idea in my own time of using: include extension('CheckUser'); ^_^ Of course, that's a little bit of a visual hack I came up with. 'extension' would be an actual function. Designed with the task of outputting a string for inclusion of an extension. Nonexistant extensions and such would be handled by a die statement inside of it... Or even better, I could let a configuration option make the function silently pass nonexistant extensions over by passing the name of an empty but existing file and write out to the debug logs that the extension could not be loaded. ;) If you get the thought, it would mean that accidentally removing the files for an extension wouldn't crash your site, it would just silently work without the extension.
But, that's just a little tangent thought. And it's extremely limited, like how it is limited to only a file, and is required to output that file even if it can't fine one.
My thought was a refactoring on how extensions are actually done. Rather than making extensions a tangent thought where we give them a bunch of hooks they can subscribe to, and beyond that do extremely little to interact with them and simplify how much the extensions actually need to do on their own.
I thought of actually integrating the notion of an 'extension' into core a lot more. One of the ideas was an Extension class.
- An extension subclasses the Extension class with it's own class to
identify itself.
- Because classes are outside of the scope limitations, we can delegate
inclusion of files to anywhere, including functions which are easier for users to understand.
- We can have the extension store it's configuration options inside of
it's own object. -- This makes sure nothing can ever collide with other extension variables or core variables. -- The Extension's class can pass itself into any class that it creates. And as a result let them access the configuration options to use.
- The core Extension class would be preloaded with a number of useful
methods for extensions to use.
While we're at it, there was something that I discussed with TimStarling. Rather than using wfLoadExtensionMessages, and being forced to load every single one of them when we need to find a single message for a MediaWiki: page. There is another potential way to get messages which does not require us to load everything and reduce performance. A lot of extensions use prefixes. And that is a real fair bit of them. Nearly every one in SVN has it's own unique way to start the names of it's own messages unless it's using a basic word. There is potential for an extension to register a message prefix with the system. And then, when MediaWiki needs to find a message, instead of loading all the messages for every extension it would check the name of the message for a registered prefix, and load the messages for the extension if needed. Tim even tells me of some sort of text tree I think it was, which would suit this better than iterating over and entire array to search for a prefix.
As for identification of the extension itself. We could put that kind of data into a method in the extension's class, and instead of using a global set every load, and unreliable if extensions don't identify themselves. We could even list on Special:Version "X unidentified extensions installed."
And, we can even reduce how much is loaded. A lot of extensions repeat functionality of certain things. One type of thing for example is pure Parser Function extensions. Ones made purely to create a new ParserFunction. We could do a number of things with this kind of extension. Firstly, we could subclass the Extension class and preload important types of configuration which these extensions would normally do on their own. Meaning that the actual work needed for extensions this simple would be reduced. And there's something even better. When do we even need parser functions? We need them in the Parser, we need them in the parser, we list them on Special:Version... But honestly, we don't need to load them every page view. And that's what a lot of extensions using the body file tactic do. In fact... We go and register ParserFunctions by making a call to $wgParser for each and every one of them. What if all the things on the page which needed to be parsed were actually already in the cache? We'd have to go and unstub the Parser class just to register a number of parser functions which aren't going to be used. And honestly, while there are still a few messages which are parsed for each page load, it would be quite possible to cache those with the page title and make it so that at some times when viewing MediaWiki you don't need the parser to ever be unstubed. This could be said for a fair number of different things. Why load everything, when only one of those things is needed? So we could potentially group out different things that extensions may add and have the extension setup callbacks of things to load. And so we'll only load various parts of the extension if they are actually needed.
~Daniel Friesen(Dantman) of: -The Gaiapedia (http://gaia.wikia.com) -Wikia ACG on Wikia.com (http://wikia.com/wiki/Wikia_ACG) -and Wiki-Tools.com (http://wiki-tools.com)
Sergey Chernyshev wrote:
Dan,
I think it's perfectly fine to create this documentation within MediaWiki.org - there is no need for special features on the site, just documentation, right? It seems to be a natural place to search for such information.
As for code generator, I think it's an overkill to start with such
complex
thing - getting just boilerplates is a good short first step which will benefit generator once code stabilizes. Moreover, code can be included
right
into wiki pages instead of SVN to minimize learning curve because people
who
use SVN are already less prone to coding mistakes then people who just copy/paste and those are the most important people to target.
I also created Widgets extension partially to help eliminate those extensions that just print out some HTML based on the input without employing much of the logic - they all can be replaced with templateing language instead (Widgets uses Smarty). I already converted my
SlideShare
extension to SlideShare widget to start with.
I'll be happy to be a user of such documentation and best practices documents and help "debug" them ;)
Sergey
On Fri, May 9, 2008 at 3:15 PM, DanTMan dan_the_man@telus.net wrote:
Unfortunately there really isn't good documentation on creating extensions for MediaWiki. And a lot of the existing documentation is badly out of date. (This is kind of the reason why we still see a lot
of
use of the SpecialPage::addPage method when it has been depreciated).
Actually, JaeSharp once poked me to help start on creating a good
source
of help. I've got SMW and a good setup, cept I need to get God to watch PHP to keep it alive. I could create a developer help wiki for
MediaWiki.
^_^ As for the boilerplate code... Honestly, JaeSharp was planning on creating a kind of generator code... Like how rails has generators to create scaffolding (models, views, and controllers which already work out of the box). That way extension developers could simply run a script with the name
of
their extension, and a bit of input on what kind of things they are using... Do they want it to not output i18n files, any special pages to create, any parserfunctions that need a i18n.magic, or extension class. And create relevant files from that.
~Daniel Friesen(Dantman) of: -The Gaiapedia (http://gaia.wikia.com) -Wikia ACG on Wikia.com (http://wikia.com/wiki/Wikia_ACG) -and Wiki-Tools.com (http://wiki-tools.com)
Sergey Chernyshev wrote:
Dan, thanks for this long overview, is there a wiki page on
MediaWiki.org
that describes all this? If not, I'll just refactor your email to a
page
if
you don't mind.
It probably also makes sense to maintain some boilerplate code as well
so
new developers can have an easy start.
Sergey
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l