There's a few obvious ones like HTTP information, current node, etc., but we probably want to get a handle on the "typical" context values we should be dealing with, or at least a good sampling of them.

To be specific, we're looking for things that:

  1. conform to the definitions of Request Context and Derived Context;
  2. currently have a crappy one-off way of accessing them in core or some popular contrib module;
  3. should be folded into the central context system.

I have started a list below. Please offer additional suggestions and I will incorporate them back into this list as we go. Hopefully that will give us a better picture of the use cases we need to handle.

Request Context

  • HTTP Method (GET, POST, PUT, etc.)
  • HTTP request domain
  • HTTP query parameters (aka $_GET)
  • HTTP request body, both parsed (aka $_POST) and raw
  • HTTP Cookies
  • HTTP headers. There are a lot and should have common handling, but a few key ones are:
    • Accept (the mimetypes being requested)
    • Authorization (for HTTP auth, etc.)
    • Requested domain
  • Pager state (derived from HTTP GET)
  • Drush command line switches

Derived Context

  • Path information (derived from HTTP GET 'q' plus aliasing)
  • Is the current path an admin path?
  • Current node (default: the thing specified by node/nid)
  • Current user (default: derived from the session)
  • Current language
  • Current organic group (default: derived from current node)
  • Active theme (default is purely configuration but could change based on HTTP GET information)
  • Browser information (derived using WURFL or similar)

Comments

DjebbZ’s picture

Does it make sense to in lure domain and subdomains ?
Also a thought about some new HTML5 features, local storage and geolocation. They're both somehow derived context from the client, but rely on the browser support and are accessible through JavaScript only AFAIK.

catch’s picture

$_GET['q'] is not really request context at all, sometimes it comes from the request, but more often than not it doesn't.

http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/reques...

http://api.drupal.org/api/drupal/includes--path.inc/function/drupal_path...

Adding some more:

menu_get_object()/loader functions in general. taxonomy/term/n and node/n/comment/n aren't mentioned here for specific core implementations.

User categories :(

arg() is not always used to get the full path, sometimes it's used for arg(0) == 'admin'.

hook_admin_paths()

Block module allows path wildcard context (more or less 'directory') for block visibility. An example would be showing a block on project/* even if that applies to multiple router paths.

menu_in_active_trail()

voxpelli’s picture

A few thoughts:

I don't think Request Context should refer to "HTTP GET information" and "HTTP POST information" by those names - rather I think it should refer to them as something like "HTTP Query Parameters" and "HTTP Request Body" - this due to them not being tied to the HTTP methods in any way.

The "HTTP Request Body" should probably be exposed both raw and parsed - which for form encoded POST requests is made by PHP, but which we have to do ourselves for any of the other HTTP methods (like PUT) or any request body with a non-form encoding.

When files are involved the parsing gets extra tricky - because then the forms data are multi-part with some parts possibly being rather big binary files, which PHP for POST requests has already parsed into $_FILES even though they really are part of the request body. We might want to support multi-part request bodies elsewhere (Services currently doesn't) but anyway we need to support very big binary files (Services does this by always working with streams - doing OAuth verification on a stream, writing a stream to a file or loading the stream into a variable)

The HTTP method should probably be part of the request context - this should support alternate ways of specifying PUT and DELETE as the Services module does.

Regarding Cookies - for alternate authentication systems like OAuth and HTTP Basic Auth we would need to know the Authorization header.

To know in what format the response should be the response context should probably include some kind of "accept" thing - but due to the complexity in parsing that one it should probably not be an attribute but rather a method like: $responseFormat = context::preferedResponseFormat(array('application/json', 'application/xml'));

yoroy’s picture

Related: I just asked a similar question in the Context UX thread on gdo: http://groups.drupal.org/node/137469#comment-512479, but more specific as to what core contexts there are and might be exposed in a UI: http://www.youtube.com/watch?v=7VOkLzD3yDs is a < 2 min. sketch that frames that question.

Nick_vh’s picture

The permissions of the current user for showing certain information. Maybe more information on this topic can be found by exploring the modules people wrote for the context module? Such as taxonomies, facets/search based context. Even the presence of a certain field regardless if it is a node or something else?
+ I am in favor of this client recognition (Browser/Client properties) as a context for plugins to activate. (Suggestion of DjebbZ)

perusio’s picture

Well perhaps I'm misunderstanding this. But why should the 'Request Context' be tied to a particular HTTP method? I concur with voxpelli.

Also why shouldn't the Request Context include HTTP headers? I'm thinking of two cases right now where that will make sense:

  • Relying on some sort of internal server mechanism for handling downloads of private files.
  • Relying on some sort of internal server mechanism for providing secure downloads.

Also I think that enlarging the 'Request Context' definition would allow for a pluggable caching system that kicks in as soon as possible and avoids going through some other additional layer.

I admit that my thinking is colored by the usage that CTools makes of the word context and that a 'Request Context' should be whatever I need to return an adequate response to the client. Not tied to a particular HTTP method or some peculiarity of the Drupal way of routing requests.

corbacho’s picture

If we want to push further Drupal as a mobile platform AND HTML5, it would be great to have all the information possible from the browser.

In the client side, we have the excelent Modernizr library by Paul Irish to detect features in the browsers. But what about the server side?

Could be possible, the same way than now with the cookie has_js, to have access to features of the browser?

I found this php Modernizr library , but I'm not convinced of the approach.

my 2 cents

mfer’s picture

A few things I would like to see:

  1. The request type (POST, GET, DELETE, PUT, etc). If we are going to support more services we should have easy access this.
  2. The HTTP request raw headers.
  3. The request response type. We often assume text. We should have easy access to see if it's javascript (application/javascript or text/javascript) or something else all together.
  4. The current page URL as a whole and it's parts.
  5. The date/time of the request. I realize this may change some milliseconds over the life of a request and this shouldn't be used for performance or anything. But, one date/time associated with the request would be useful.
  6. Any timezone information available. Not sure if this should be attached to the user object, the top level, or both.
  7. The menu object for the current page callback.

These are just off the top of my head. I imagine others will surface at some point.

DjebbZ’s picture

As of #5 and #7 I don't think extensive browser/client properties should be calculated and derived from context. The modernizr js library is useful in the browser side. We should make the request handling process lightweight so if we need to perform tasks or manipulate the DOM we could just rely on super fast js and Ajax (which is partly one of the goal of the initiative, and a key to make Drupal a robust platform for mobile and HTML5 dev). Remember that the context stuff should work for the typical web browser, but also for web services (no browser), drush (no browser), testing framework (no real browser).

About permissions, the response holds your answer. It's 403 if you don't have access. Or you handle this in your page (like Panels do) but this is business logic that happens long after the beginning of the request. This is described as "the response controller" in the definitions.

I second catch, voxpelli, persuio and mfer : these are good ideas for information that we can directly obtain in the request or derived context and necessary to provide the proper response.

jwilson3’s picture

I could see the benefit in having a context handler for things that don't qualify as a "regular 200 response" from Drupal. Anything that changes the response mid-stream from that of something expected, to something the user really didn't want or expect to see, could potentially be considered a derived, "transitory" context, or perhaps as a sub-context or state of a Response object. For example: a call to drupal_goto, 403 (Access Denied), 404 (not found), Drupal's Site Offline (Maintenance Mode), Drupal's unexpected error handler. Perhaps it may end up being that these are things that exist to too early, or too late in the bootstrap lifecycle to be meaningful for a module to "do something" with the context, but just trying to think outside the box for a bit.

Crell’s picture

voxpelli: Excellent point regarding HTTP query params. I've updated the page accordingly.

Re #10: Regarding non-200 responses, see the discussion here: http://groups.drupal.org/node/148149 We absolutely want to be able to separate handlers for 403/404 on different request types.

Timestamp of the request: I don't know that we want that in the context. It's already a constant as of Drupal 7. We can't get much faster of an implementation than that.

Re #6: We're using "context" here to mean something a bit different from ctools and from context.module. Just to keep life interesting. :-) For our purposes it's an enhanced request object, essentially. (The request object is the request context, the derived context is Drupal-specific stuff.)

Since all information is calculated on the fly, I am not sure that the mime type is necessarily a method. $context['preferred_mime'] (or whatever) would internally fire a method call on another object that can do whatever computation is necessary to determine the mime type we're going to use to serve this request. And that happens on-demand, so if it's not used then it's never computed.

catch: Actually $_GET['q] is part of the request context, since it's an HTTP query parameter. What is derived context is the Drupal path on which we are operating. Right now we write that back into $_GET, which is evil. The requested path and parts therein (arg()) are separate things and part of the derived context. I've updated the list to be clearer there. Some of the other stuff you mention, such as admin path or active trail, I am not sure belongs in the context object proper. I'd like more feedback on that question. (That's what this thread is for! :-) )

menu_get_object() I see conceptually going away, replaced by $context['node'], $context['user'], etc. At least that's my current working thought.

Regarding server-side browser detection, all of that is derived from the request context (aka HTTP Headers) using, essentially, user-agent sniffing. That would be a form of derived context. I am not convinced we should be doing that in core (I defer to the HTML and design gurus on that one), but it should be doable from contrib, certainly. I've noted it as a general line item for now.

Are there any other derived context keys we should be thinking about? I can't believe node and user are it. :-)

Good stuff, folks. Keep it coming.

jherencia’s picture

Subscribing...

catch’s picture

catch: Actually $_GET['q] is part of the request context, since it's an HTTP query parameter.

It's an HTTP query parameter, but it is only taken from the request if you don't have clean URLs enabled, otherwise we figure it out and fake it in _drupal_environment_initialize(). This is separate from what path.inc does. This might possibly be splitting hairs but putting a wrapper around $_GET is not going to work for this.

There are some other places (possibly including core) where we need to fake $_GET - thinking of setting pagers and tricks with menu_get_item(). Probably most of this could be solved by having a current path (and pager position) property and sometimes deriving this from $_GET, but sometimes not. But there is not a simple dividing line between request and derived, and things will break if one is put there without accounting for some of those cases.

DjebbZ’s picture

We talk about nodes and users, should we be talking about entities also ? Some may have a view page. And when looking at a page created by Views, or Panels, should derive them ?

#2 : Until block module is re-written (we all hope this right ?), deriving the visibility criteria for blocks is important IMO. Admin paths is also a good thing, it may help for theme switching and/or permission to access the page amongst others.

Server-side browser detection : this way of thinking isdeprecated :) Front-end developers community understood it, and introduced browser-capability detection. The modernizr js library is an excellent example. Basically you don't care about whether the client is using IE6/7/8 or Firefox 3.0/3.5/4.0. You just want to know if it support the feature you're interested in (video tags, css3 effects, local storage, geolocation API, whatever browsers may support or not). Really easier to use, and no nightmare to maintain a map of "Browser version => capability => usage", because you basically take out the browser version part :).
I've taken a small look at the modernizr php library suggested in #7, but it relies on the javascript version storing a cookie of what's possible that is then used by the php version (forcing a reload of the page). Not very reliable. And projects like WURFL are hard to maintain (so many browsers versions, especially in the mobile devices space). So I suggest we don't provide extensive information if we cannot provide it reliably.

- Thinking out of the box -
The context object may/should answer these questions in general : WHAT ? WHEN ? WHERE ? WHO ? HOW ?
WHAT : the page requested : this has been well described above
WHO : the user requesting it : human, bot, drush, testing, search engines crawlers, etc. So the browser detection is a user type detection ?
WHERE : well, we already have the IP, we don't need IP-based geolocation in core :) (contribs already exist to provide that)
WHEN : we have the time of the request, I leave you guys about the specifics whether using or not the Drupal 7 constant.
HOW : I don't even understand this question :) The way I conceive it may have some overlap with the WHO, but it's not clear in my mind if we should even answer it.

mfer’s picture

@DjebbZ Sever side detection of browsers has not gone away. For example, Google and Bing websites both detect if you're on an iphone or android. If you are they serve up different html, css, and js which take advantage of technology in the phones browser. It's really quite slick and performant. We should not preclude it nor should core do this by default. Core should make the context object extendable and let contrib deal with this.

@crell the requested mime type should be in the context object. It's part of the request header. If a client requests a JSON file or an XML file we should be able to see that in the context object. For example, if jQuery.getJSON(), jQuery.get() (looking for JSON), or jQuery.ajax() (looking for a JSON response) are called they send that they accept "application/json, text/javascript". This is good to know and should be available on the context object.

Crell’s picture

catch: drupal_environment_initialize() I expect to largely get incorporated into on-demand logic in the context object. Or at least I hope so. What it's doing with $_GET['q'] is overwriting it with request_path(). Presumably that need goes away and gets replaced with $context['request_path'], which is probably largely a copy/paste/modify from request_path(). After that, anything that reads $_GET['q'] directly instead of $context['request_path'] should be treated as a bug.

DjebbZ’s picture

What about the global $base_url ? This is a derived information about the Drupal installation requested.

DjebbZ’s picture

@mfer : I didn't about advanced server-side browser detection. Agree to make the context object extendable about this.

DjebbZ’s picture

Another derived property : the drupal version ?
(sorry I don't mean to pollute the thread, ideas keep coming in a non-predictable order :)

mfer’s picture

@DjebbZ I think the more input the better. As I understand it, the context object is about the current request being processed by Drupal. Between requests the Drupal version isn't going to change and isn't part of the request. There is already a constant with this information which would be much faster than attaching to a context object about the current request.

DjebbZ’s picture

Ok mfer, good to know, it keeps me motivated :)

Crell said in #11 that we were all about nodes and users. Let's load (or reference) taxonomy term and vocabulary when we visit taxonomy/term/[tid] in the context object (maybe catch already said this in #2).

Does it make sense to have a reference to the active database connexion ? If the context object is changeable, maybe it could help querying other databases during page request ? (I'm not sure I'm saying something meaningful/useful/possible).

What about the path aliases ? We may need to know if the path requested is an alias and where it points to, or the alias(es) available for the requested path.

Crell’s picture

The database connection is a service object, not contextual information. It's not going to vary based on the incoming HTTP request. We may or may not be adding a service locator later (similar concept to the context handlers but a separate channel), but that's outside of scope for right now.

pounard’s picture

@#2 $_GET['q'] could be become contextual information. If core tends to a composite view *MVC/PAC implementation in order to serve ESI blocks, for example, each block may have it's own 'q'. Moving down this information to the block level could easier things such as ESI blocks (which wouldn't be blocks anymore but controllers). Plus, you could pass any other context information (more generally top level elements, such as a node being displayed etc) as associated GET parameters. This is a bit off-topic, just a simple though about $_GET['q'].

joachim’s picture

> We talk about nodes and users, should we be talking about entities also ? Some may have a view page. And when looking at a page created by Views, or Panels, should derive them ?

Yup, the current entity and more generally, 'What is taking charge of producing the current content?' -- that could be a single entity, a general page callback like in blog.module, a view, a panel, and so on.

lpalgarvio’s picture

sub

corbacho’s picture

Interesting slides about Context in Mobile (starting at slide 52) (via John Albin)
http://www.slideshare.net/yiibu/muddling-through-the-mobile-web

How to get context from both sides: Server & Client.

In the first request, it can be used Server-side solutions like Open Source Wurfl, and deliver Javascript that will communicate back even more context information (a second request) syncing both. All this information gets stored in a cookie.

If it's not in core, the API should provide very easy to add via contrib this kind of contextual device information and be available in the theme layer.

Gábor Hojtsy’s picture

Looks like nobody noted that yes, but on language, Drupal 7 supports different language types with "interface", "content" and "url" as the core defined types (and contrib can define more types, even though I have not seen one yet). These are used to display the interface, content and generate URLs respectively. For these to be different imagine this scenario:

Your site uses session information to display language, the URLs are not different. However, your site has English and Russian, and you definitely don't understand Russian but need to manage parts of some Russian nodes or other Russian content. You need an English interface to manage details even for Russian nodes, so you at least understand the content pieces. Having an admin interface different to the content language is a very very common feature request. So you end up with URL language none, interface language English and content language Russian. Contexts should be able to carry these details.

lpalgarvio’s picture

could not agree more.
interested to see how language selection will play out with contexts (site default, user account, browser, session, url...).

Sessions and URLs?
http://drupal.org/project/session_api
http://drupal.org/project/purl

Crell’s picture

Gabor: Yeah, language is tricky. At the moment we're not trying to solve all pieces of it, but make sure that the architecture we come up with allows it to BE solved.

Would it be sufficient, do you think, to have "user language" be one context item (which could derive from URL, session, user pref, domain, or whatever), and "object language" be another?

dmitrig01’s picture

Seconded LPCA -- $_SESSION should probably find its way into the context object.

Also, what about response format? I know response format could be calculated based on several different things, but all of those seem to be already in the context object.

Crell’s picture

Session is an interesting case. On the one hand it is legit incoming data. On the other hand, we need to be able to write back to the session (obviously), and the context object is read-only. So... not sure there.

The response format is mostly derived from the HTTP headers, I think, but a handler could be implemented that uses some other information as well.

DjebbZ’s picture

#29 Just wondering, how would we properly derive "object language" (which I presume corresponds to Gabor's #27 "content langauge") for a node with mutlilingual fields ? If a node is in English (or language neutral), but all its fields are saved in Spanish, what do we do ? Use only the "main object language" ?

#26 I must totally agree with you. Crell, please look at the slides, and ask yourself : can we make Drupal a cool mobile CMS ? Giving developers tools to create adaptative content / responsive design is not a feature by these days, it's a requirement (IMO).

Crell’s picture

DjebbZ: I agree entirely. Phase 4 of the WSCCI initiative involves moving to a more flexible, more robust layout mechanism inspired by panels. That should help with mobile and responsive design. However, the bulk of that work is the HTML markup we use by default, which is not something WSCCI is trying to address.

sdboyer’s picture

All of this is great...if it's an HTTP request. Howzabout a Drush/CLI context? I don't know what all should be stored there, really (nor am I sure it's especially up to us to care - and that has interesting architectural ramifications of its own) but it does seem to suggest there ought to be a high-level contextual dojobby somewhere indicating whether we're responding to an HTTP request or not.

Back in HTTP-land, though, I think it's also worth placing (sub)domain info into the context. Actually, with the way drush handles multisite, that probably applies there, too.

Crell’s picture

I've added domain info to the list of HTTP header items we likely care about.

For Drush... I'm not entirely sure. The goal is to be able to separate the interface of the context from its origin, so that you could run most code equally well in CLI or HTTP mode. There probably are keys that make sense only in CLI mode, however.

At the moment, I'm inclined to say "we don't care". I'm not looking to make a complete and definitive list of context keys here, just to make sure we have a sufficiently representative sample that we make sure we cover all reasonable *types* of context.

I'll add Drush command line switches to the list as well, though, which should fall into roughly the same usage pattern as HTTP headers or query parameters.

Crell’s picture

Project: Butler » Drupal core
Issue summary: View changes

Add domain to the list of request context values.

lpalgarvio’s picture

Project: Drupal core » Butler

perhaps it could be useful to list these contexts in the todo list with a priority, so we can manage better the most important ideas and deal with them firstly

AndrzejG’s picture

Prioritizing is a must as the task and possible resulting context system seem to be extremely complex. Question is what criteria should be applied to prioritize.

If we agree, that Usability and performance are most demanded by the Users, than the speed of Drupal is one of the keys. As mentioned in other places, succeeding versions of Drupal get slower and slower. In order to shorten the average response time the priority should be placed to the elements of context for which the response takes shortest time and least computing power. The general rule is "make small things first" - in such a case the average waiting time of the User will be shortest.
Not the biggest tasks, not "most important" ones but smallest and shortest.

Above rule is related somewhat to the concept of system. In general, system can produce the response or the next request - for simplicity let's say request to the database. According to WSCCI definition "The context of a request is all of the data and metadata that derives from the incoming request, either directly or indirectly." This last statement ("directly or indirectly") is a key.
Proper answer often is derived from statistics. First, list the context elements requiring 1 call to database, then those requiring 2 calls etc. Cumulative series of the typical frequencies of such elements will show the breaking point which should be treated as indicative point of the cut - the cut dividing all set of context elements to at least two subsets: those requiring "short and simple" response and those requiring "long and complex" response.

BTW 1, above statistics is one of the basic techniques when implementing so called "group technology", aimed at optimum utilization of processing resources at the same time as attaining optimum process efficiency in the cases of moderate variability of subprocesses and results. Next stage is the analysis of similarity of routing paths, but this is another story. The optimal system for such technology usually consists of collaborating "processing centers".

BTW 2, as non-coder I don't know anything about systematic nature of "the object". My voice is that of industrial engineer.

Crell’s picture

AndrzejG: The intent is for all context information to lazy-load. So unless it is requested, all context information takes 0 DB calls. If it is requested, then we know it's going to be used so whatever it's cost is, it's a cost we know we need to pay.

The goal in this thread is more to make sure that we are able to handle all reasonable *classes* of context information. Eg, we know that there's information that we can pull straight out of HTTP headers mostly verbatim... can we handle that? Yes. There's context information from the headers that takes a little futzing to turn into useful data. Can we handle that? Yes. There's context information where we need to mix header information with DB information (like "current node"). Can we handle that? Then there's context information where the value could conceivably come from multiple sources depending on user configuration. (Language is a good example here.) Can we handle that? What about context information that depends on other context information that depends on other context information that depends on HTTP headers?

Those are the sorts of questions we're after in this thread (which I may not have been entirely clear on before; if so I apologize).

AndrzejG’s picture

Crell, more request for excuse is from my side, that my "lectures" :-) are often not in line of the discussion. Or, they take the same questions from other, very different point of view. In this particular case I think above is different point of view at Your last question about dependencies. Calls to DB of course is my fault as I don't understand how the context element is processed. So, please replace them with something like "elements requiring more steps in handling them".

BTW obviously my activity is like that of blind in the fog, need some feedback if it is useful or not.

joachim’s picture

> There's context information where we need to mix header information with DB information (like "current node")

I think it was EclipseGC who gave this very good example on IRC:

Suppose we have a block we want to show on issue nodes, displaying information about the project node the issue belongs to.

How would the context data the block needs be represented?

Should we have modules that load up context add predicates in addition to basic data, so the issue node adds:

- node:ID
- node:parent_project:ID

Crell’s picture

joachim: A fine question! That's more what I want to get at in this thread. I don't know at the moment how we'd do that, although it would no doubt be affected by the results of #1177246: Context values: Keys or objects?. (We need someone to code that, btw.)

AndrzejG’s picture

Maybe it would be reasonable to analyze how similar issues are already solved ( OG 7.x - groups User belongs to; CNR) and already failed (Feeds, Field Collections - I see an incomplete definition of "attachment" but maybe I'm wrong).

Rolf van de Krol’s picture

There popped up a discussion whether the current theme is context information or not. I'd say: yes it is, because the fact whether the theme is relevant or depends on the request (XML or JSON does not have a theme), and the choice of the theme also depends on the request (different paths can use different themes).

Any opinions on this?

Stalski’s picture

I generally agree. I think there are cases where json responses will have themed (and thus template specifics) output.

DjebbZ’s picture

Agree. Theme becomes a derived context information.

Stalski’s picture

And I guess this context key could get overridden by a users theme. But I guess since #1177246: Context values: Keys or objects?, we can start thinking about that.

Crell’s picture

Project: Butler » WSCCI
Version: 7.x-1.x-dev »

Refiling to the sandbox queue...

webchick’s picture

Project: WSCCI » Drupal core
Version: » 8.x-dev
Component: Miscellaneous » wscci

Per catch, and blessed by Larry, moving this and all other WSCCI issues to the Drupal core queue.

DjebbZ’s picture

Whether we're visiting the front page or not is a derived context information, or not ? That would impact the core function drupal_is_front_page().

Damien Tournoud’s picture

Adding a few things:

  • conf_path() is definitely a derived context
  • From that, we have all the configuration parameters specific to the site (database credentials, etc.)
  • all the communication between different parts of the page (for example, between block) needs to happen via the context too, like:
    • Current node being viewed
    • Current Search API request (for facets blocks)
    • etc.
DjebbZ’s picture

Maybe a stupid thought, just thinking out loud : if a context activates some plugins (Cache plugins, Views plugins, Database plguins, whatever plugins in fact), should a list of all activated plugins be available in the context object ?

sun’s picture

Title: What common context information do we have? » [meta] What common context information do we have?
Priority: Major » Normal
Issue tags: +WSCCI
Crell’s picture

Component: wscci » base system
Status: Active » Closed (fixed)
Crell’s picture

Issue summary: View changes

Add Drush information to the list of context.