display | more...

First of all, you may want to begin by reading the previous two entries in this series by kthejoker: Coding for E2: A primer and Coding for E2: E2 Syntax. You might also be interested in first reading edev: Quickstart. In this entry, I'm going to try to guide you through some examples of first finding where the code that you may want to change is, so that at least you can get started with an idea of what to do.

Finding the code in e2 that affects whatever functionality you're interesting in changing can be difficult. Broadly, the code can be in one of five places:

  1. Nodes
  2. The server's current Everything Engine, hereafter abbreviated to "ecore"
  3. Standard Perl libraries like CGI.pm
  4. Standard Javascript libraries like Scriptaculous
  5. Perl cron jobs running in the server

Thankfully, most of the code that you will want to see and modify is readily available to you in a node somewhere, but just finding which node can be a challenge. The running ecore is accessible from Gigantic Code Lister, along with other bits of code like htmlcodes (currently only available to admins; trying to change this ASAP so that edevites can participate too). External libraries like CGI.pm or Scriptaculous are found in external sites. Our global variable to access the CGI.pm object is $query; so you'll see that running around the code now and then for creating form elements. Lastly, the only way right now to look at the cron jobs is to have ssh access into the server. I would like to change this soon so that edevites really have read access to all the code they need in order to make e2 better. We'll see.

But like I said, most of the code is in nodes and accessible to edevites as long as the nodetype is accessible (e.g. restricted_superdoc is a nodetype that is only accessible to admins). You can see who has access to a particular nodetype by going to the nodetype node ("everything's a node", remember?). The codeful nodes can be further broken down into the following main categories:

You can go to List Nodes of Type in order to get the full list of each nodetype if you wish. Each of those nodetypes requires an explanation of what they are for, what kind of code it houses, and how do you find it.

superdocs and variations

The superdocs and their variations are nodes that display by themselves and often perform some kind of code. When you visit them, you'll see that they often render some kind of content. Let's look at a particularly simple example, the Fezisms Generator. Go to the superdoc node and hit viewcode in your edev nodelet.

As explained in the last article in this series, you'll see some raw HTML which isn't filtered in superdocs like it is in writeups and discussion posts. Immediately you'll see the magic "[%" signaling "Perl code begins now" and some simple Perl code that defines two arrays of things thefez might say. The Perl block of code ends with the symmetrical "%]" There are two blocks of Perl code here, and these blocks are essentially Perl functions: e.g. they can return values like any Perl function, or will return the last value in them when parsing through them. In this case, the Fezisms Generator returns two random chunks from each of the @wit arrays in each block of Perl code and that's all, creating enduring hilarity for the ages.

The other nodetypes of the superdoc family have differences in how they handle the filtering of the HTML (for example, superdocnolinks doesn't call the ecore function parseLinks , so links in brackets aren't rendered) or the permissions associated to them. Scratch Pads is a prominent example of a node that for whatever reason is of nodetype superdocnolinks and not superdoc, but for practical purposes in terms of code is pretty much the same. More interesting examples of superdocs could be user settings and nodelet settings or even the frontpage.

htmlcode nodetype

The htmlcode nodetype is an interesting and sometimes frustrating kind of code in e2. Its original purpose as its name indicates was clearly to generate boilerplate HTML within certain nodes. For example, for e2nodes (writeups containers), we have in e2node display page the firmlink, softlink, and addwriteup htmlcodes being called with the [{some_htmlcode}] syntax as described in a previous writeup. However, because htmlcodes can also be called a inside Perl blocks with ecore's htmlcode function, their original purpose has been perverted to be used as "general purpose functions" and using their return "HTML" as a pure string or scalar with which Perl can do other things. Examples of this usage of htmlcodes are rootbeer277's dragUsers or kthejoker's isinUsergroup.

Ecore's htmlcode function for calling htmlcodes deserves special attention, since the way it works is downright barbaric in our running 0.8ish ecore. Its non-intuitive functioning has been a source of frustration and has caused bugs in the past, even as recently as this year when trying to apply call's table screening code as an htmlcode (it was impossible as an htmlcode and we had to resort to jamming call's code into ecore in the server).

Our running ecore's htmlcode code function takes at most two and no more than two arguments: a Perl string with the name of the htmlcode to call and another string with its arguments. It then performs a very simple parsing in a Perlish way to split the second argument by commas, and the resulting array will get passed to the called htmlcode's argument array @_. From the called htmlcode, you can then do "my ($foo,$bar,$baz) = @_" to recover the three arguments that ecore passed to this htmlcode.

The problem is that the arguments have to be extremely simple, since ecore performs a very low-level split on commas alone. This means, for example, that you cannot pass a writeup text to an htmlcode as we wanted to do with the screenTable function, because writeups almost certainly contain commas in them, and ecore will interpret that as different arguments. Another example is that JSON objects are strings that contain commas in them, so you'll see for instance in debate maintenance create that the notification code has to escape the commas in the JSON which the addNotificaiton htmlcode has to unescape and split upon.

There is one further bit of complication with passing arguments to htmlcodes this way and that's that ecore essentially does string parsing and macro substitutions when passing arguments. What this means is that quotation marks are not escaped either, so it's difficult or impossible to pass any arguments to an htmlcode that contains quotes, because then Perl will be unable to parse the resulting string that ecore's htmlcode creates.

Despite these limitations, as long as one stays aware of them and is careful about the argument string that goes into an htmlcode, htmlcodes can be very useful to have certain functions within the database instead of implemented in the server.

nodelet nodetype

This is also pretty straightforward: because everything is a node, nodelets are also nodes, so they can be seen like ordinary nodes in addition to displaying in your sidebar. The kind of code inside nodelets is pretty much the same as the code for superdocs; you can also put unescaped HTML inside nodelets and Perl blocks are also signaled in the same way.

I do want to mention one peculiarity of nodelets and that is nodelet sections, which are sometimes a bit difficult to find. Nodelet sections are those parts of a nodelet that you can collapse with the little + and - buttons. Let's look at an example, the Statistics nodelet. When you look at this nodelet's source, you'll see that it's a rather terse bit of code that only calls the nodeletsection htmlcode with some parameters several times. After parsing N-Wing's code in nodeletsection, you can eventually figure out that what it's doing is concatenating the first two parameters passed to the htmlcode in order to invoke yet another htmlcode. So for example, the first section in the Statistics Nodelet, "stat,personal,Yours" becomes the htmlcode statsection_personal and the "stat,global,E2" the statsection_global htmlcode. The general formula for finding other nodelet sections applies to other nodelets.

htmlpage and container nodetypes

These are the nodetypes that are used to render nodes. The way it works is that ecore fetches a node, sees what htmlpage goes with this node, sees if that htmlpage has a container, if that container has another container, and all the way up to a parent container, and then starts rendering the page by calling the top container, replacing the infamous CONTAINED_STUFF in the top cotainer with the next container in the list, all the way down until it reaches the htmlpage and voilĂ , the node is rendered, along with the nodelets and all the goodness that is e2. This chain is also determined by the current theme you're using, Jukka, classic, or Zen.

You can see which htmlpage is being used to render the node you're looking at because it will be in your edev nodelet. If for example you want to add a new text field to the homenode edit page, you can go to your homenode, edit it, look at your edev nodelet and observe that classic user edit page is the htmlpage that it's using. This is what you would have to patch to add another textfield to the homenode edit screen.

Not all htmlpages have containers, though. For example, the fullpage display page htmlpage is very simple and has no container, the jscript nodetype is another example that has a jscript display page without a container. Chatterlight is an example of a node of type fullpage, and if you look at its code (put "&displaytype=viewcode" in the query string in the address bar of your browser when visiting chatterlight), you'll see that chatterlight does a lot of work of its own to render the page without relying on the default formatting that containers provide.

In particular, most of the site-wide CSS for the Zen Theme are provided in zen container and zen stdcontainer. This is where you can find a good chunk of the work that ascorbic and kthejoker did to bring e2 out of the dark ages of table-based layout and into a new era of CSS goodness.

opcode nodetype

An opcode is a bit of code for e2 that performs certain actions; it's called in conjuction with other bits of code. The way to call an opcode is to pass the "op=$opcode_name" CGI parameter to e2 somehow, either by a query string in a GET method or by POST. For example, if you look at chatterlight's rendered HTML source in your browser, you'll find that there is a hidden CGI form element

<input type="hidden" name="op" value="message" />

which means, "when this form is submitted, call the message opcode", and is exactly what will happen. Most things you think of as operations in e2, voting, cooling, sending /msgs, are opcodes. It's instructive to go to List Nodes of Type and browse through the opcodes that we have available.

dbtable nodetype

This is the nodetype that ecore uses for representing tables in the underlying MySQL table that houses all of our data. It isn't really a nodetype that contains code except in the sense that all the of e2's data is ultimately in dbtables, and if it's data in a node somewhere, like much of the code is, then it's in a dbtable.

You will often see ecore calls of type $DB->sql* which will invariably mention a dbtable in their first or second argument. If you ever need to refer to the structure of the underlying dbtable, go look at its node, which looks very much like any other MySQL table description, telling you what columns the table and their type. Unfortunately, unless you actually look at the data in the columns, it's not always easy to guess what's in each column. In case of doubt, consult an e2coder who will be able to make a quick query on the table and report back on its contents.

maintenance nodetype

Whenever a node, any node (and this includes writeups, users, nodeshells, because everything is a node) is created, updated, or deleted (nuked), ecore will call a corresponding createNode, updateNode, or deleteNode function. Each of these nodes will check in turn if this nodetype has an associated maintenance node that will perform those operations, and if it does (most nodes don't need that much maintenance), it will execute the code in this maintenance nodetypes.

When you look at a nodetype's node (e.g. the debatecomment nodetype), you'll see listed near the bottom after it lists the permissions any maintenance nodes associated to it, if any. For example, debatecomment has debatecomment maintenance create which amidst its maintenance code has the notification code for notifiying users when a new reply has been posted to usergroup discussions. Writeups have writeup maintenance delete which in turn contains code for adjusting the XP and writeup count of users for when their writeups get nuked. And so on.

jscript nodetype

This nodetype is quite simple: it's what contains javascript to be used by e2. It has no container, so if you want to patch jscript nodes, you'll have to manually manipulate your URL and attach "&displaytype=viewcode" to the query string, or you can click on their (patch) link from javascript repository. After that, zen stdcontainer makes a direct call by node_id to Javascript compiler to place the right javascript in the header. For now, async voting gets embedded directly by zen stdcontainer in a separate line without going through javascript compiler.

I should remark, this isn't the only bit of javascript in e2. We have lots of other bits of javascript in e2 embedded directly into the code without going through jscript nodetypes; TinyMCE is one prominent example of one. Usually it's easy by looking at the rendered page to guess which node has the embedded javascript when the javascript isn't being served by a jscript nodetype, though.

Other codeful nodetypes

These aren't the only nodetypes that can hold code, but they are the most important ones. We have minor nodetypes that only have a handful of nodes like the notification nodetype that handles what gets displayed in the Notifications nodelet or the achievement nodetype that has nodes with code that determine when an achievement in My Achievements has been... well, achieved. This should be plenty to get you started, though.

That's all for this node. Gigantic Code Lister, currently only available to admins, lists all of the code in the running ecore as well as optionally all the htmlcodes. Also in the server, under /usr/local/everything/bin, you can find some Perl scripts that cron calls to perform maintenance tasks like moving writeups from Node Row to Node Heaven. This should be enough to help you find your way around the code.

Happy hacking!

Log in or register to write something here or to contact authors.