What i want to do is, i want to have original views field handlers (starting with views_handler_field and all in the cascade which inherits from it) altered to implement a new functionality. I don't want to change the fields types of a view to another ones, every time i want to implement the new functionality.

Since php doesn't support altering of class definitions (overriding methods before instantiating), this is not an easy case.

I see there a way creating a new handler inherited from every handler that inherits from views_handler_field, then implementing hook_views_data_alter() to use these handlers.

But this is not a very elegant solution, besides that, with this method, i can implement this new feature only for original views handlers, not for possible handlers from other modules, not in the core. Some ideas? Or is there a possibility of developing a new mechanism in views for doing things like that? Any ideas on these mechanisms too?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

merlinofchaos’s picture

Wow. Uh. I have no ideas at all on this one. Getting the cascade is pretty rough, and nothing comes to mind that could make this possible.

Why would you want to do this?

dawehner’s picture

You might be able to use hook_views_handlers_alter (if it exists :) ) and set another path for a certain handler.

I'm not sure whether this would be possible in d7.

wapnik’s picture

I want to build a module (some modules), that will implement features, that views don't want to implement by design. For example regexp/php field value rewriting. There are some modules doing things like this (views_customfield), but as i wrote before, i think a better concept (on how to extend views functionality in general) would be not to have to change the type of the field every time to a new one, but only to enable the module implementing it. I'm talking about an existing view of course. I as a user would expect views and modules extending it to be working like this.

wapnik’s picture

What about multiple interface inheritance?

wapnik’s picture

@dereine: If i change the path to the handler using hook_views_handlers_alter, the original handler is not loaded, so i cannot inherit from it, am i right? So i have to copy the original handler and add my code to it. Is this what we want?

Or if files from both paths are loaded, i can inherit from it, but the problem with the cascade of inherited handlers still remains, cos other handlers still inheriting from the original handler.

What's changed in d7? :)

dawehner’s picture

I really suggest to just hook_views_data_alter and change / add handlers. From my perspective this is the way views is architected and i don't see a reason that you cannot do something with it.

wapnik’s picture

@dereine: the hook_views_handlers_alter + copying the handler seems to be quite less work and in advance it not only apply for views original handlers but other modules' handlers too :)

@merlinofchaos: what's your opinion?

dawehner’s picture

@wapnik

With copying i hope you mean extending. This is oop so you have often just a few lines to have your handlers doing what you want.

If you need a way to keep the previous behaviour you could also add a field with "real field" to the original field.

So this issue is fixed?

wapnik’s picture

Of course this is oop, but with copying i mean exactly copying the handler's file somewhere in your module and adding lines of code to that file.

Cos other handlers are inheriting from the original handler, i'm talking about disabling the loading of the original handler's file and loading my file with the handler extended but with same name (because of the other handlers that inherit from it to work).

As i understand your hook_views_handlers_alter (if it exists) solution right.

It's not fixed i still want to read merlinofchaos's opinion :)

wapnik’s picture

Ok that multiple interface inheritance was bullshit.

What do you think about using mixins in views handlers? Is that possible?

dawehner’s picture

A mixin is double inheritance from different classes?

We use php and not c++ :)

wapnik’s picture

Forgive me for my lack of education in oop and design patterns, i have never studied informatics at university, therefore i'm trying to educate myself this way too. :)

I know that there is no multiple inheritance in php, but there is a way to "simulate" this mixins. You can take a look at this article ("Mixin" section) if you have time and interest. That's what i'm talking about. I think design like this one can be useful in this case. Maybe.

dawehner’s picture

This stuff makes it even harder to read the code.

My oppinion is that this overcomplicates things. People might not be able to read the views code anymore.

At the end i still don't get the point. It's all achivable my extending existing classes via hook_views_data_alter. I just more effort

wapnik’s picture

The point is, i'm trying to find a way how to modify a handler with not having to register a new one.

Imagine the situation like this. Views with their cascade of fields handlers, each handler registered under it's name. If you want to use a handler that has a different functionality, you have to add a new field (in the ui). That makes sence in views core because in fact you're (as a user) not actually thinking in handlers, you not want a new handler (a new functionality) but a new field. One field has it's one handler, that knows how to deal with it, one "description" how it may function.

Ok, now other modules are registering default views, for example (the example i'm trying to improve) table wizard is generating a view for the migrate module for the purpose of data migrations. This view is using one of the handlers from the views core handlers, of course because authors of the module want that basic functionality the handler is offering.

Now here comes the user. He sets up the view in the table wizard and realizes that he needs to alter the view's fields (set by the table wizard) somehow differently that views itself is offering to him. He needs the php altering for example. He installs the views_customfield module hoping when he installs it, that his fields in his view would have this new php-rewrite-field functionality. But it's not like that. He has to change the handler for every field in his view. In views ui there's no ability to change the handler.

So now the situation with the handlers is different than in views core. The user wants one field "with two descriptions how to function". I'm talking about a situation with three elements of code reusing. Views is offering some functionality, a module is implementing it and another module wants to speak to it.

And this is achivable with hook_views_data_alter?

Or maybe the situation only needs a mechanism how to change the handler used in a view by this views_customfield after it is set by the table wizard.

wapnik’s picture

Version: 6.x-2.x-dev » 7.x-3.x-dev
Category: support » feature
Status: Active » Needs review
FileSize
1.39 KB
2.32 KB

This here is a module for testing purposes (yet), with one handler, which is a copy of a handler from views_customfield module. The module rewrites a chosen handler registered in views data and all handlers, which are inherited from it with it's own handlers. Then it dynamically generates and loads the code for handlers corresponding classes. So the functionality provided in the used views_customfield handler (a php rewrite textarea) is available in every views field.

This goes beyond horizontal reuse, which was discussed before, because it extends handlers not provided only by views core, but by other modules too. So one can have multiple modules aware of themselves, extending their features in a line ordered by modules weights.

The module needs a new hook for loading the code right before the new handler's instantiation. I think there is some work needed for rewriting default views registered by modules. Maybe a big part of the code should be in views core not in the module itself. This is just a sketch. So tell me what do you think about this.

dawehner’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev

New features are developed against 6.x-3.x

wapnik’s picture

wapnik’s picture

any feedback please

Crell’s picture

Status: Needs review » Needs work

If you're using eva(), you're asking the wrong question. eval() is pretty much never the correct solution.

As of PHP 5.2, there is no good answer for what you're trying to do. I've tried to come up with something many times. :-) Example:

http://www.garfieldtech.com/blog/magical-php-call

So far, the least-bad solution I've found is the "Extenders" approach that the database layer users. It's ugly but it's the only solution I've found that mostly works.

PHP 5.3 offers anonymous functions, but that doesn't solve the problem since they cannot be bound to objects. As of PHP 5.4 they should be, and we'll also get Traits for compile-time horizontal reuse. Whether or not that will resolve this issue I'm not sure.

(Posting here because I was specifically requested to do so...)

wapnik’s picture

I've red your article before. As dereine mentioned here few comments back, using these "mixins" will make the code more complicated (to follow). Depends on the implementation, but at least you have to (or the developer of the new handler) register methods, etc. I mainly agree with him.

Can you please give a link to these "extenders", where this was mentioned, i wasn't able to google anything.
I don't think these traits will resolve this, cos they are not dynamic. You have to write explicitly in the code, which traits you're using. Anyway we cannot wait till php 5.4 is released and gets adoption. Could be years. :)

From the point of "code clearness" of the handler class i think using of eval() is ok. If we can put the generating mechanism inside views; all the class/parents names generation, loading the "code template", modifying it and evil eval() itself too; and if we can build a good interface for it (maybe it doesn't need a new hook at all)... Well i don't know nothing about performance of it now, that's true. Can you please explain more in detail why eval() is not good here?

wapnik’s picture

Extenders, now i know what you're talking about, wrong search sorry. How i see it, that's again a kind of dirty __call magic + wrapper staff. Talking about performance it's using call_user_func_array. Using eval we can at least avoid the extender class here (SelectQueryExtender in the case of database extenders).

bojanz’s picture

Ugh, that's just awful. Anything solution that has "eval" in it is a bigger problem than the original problem it's trying to solve.

Using extenders is at least somewhat clean and avoids magic, but the fact is that we are running into the limits of PHP here, and any attempt to solve it is bound to be less than pretty, so I'm not sure there's anything Views can do to make this easier.

wapnik’s picture

Another concept. I moved a lot of the code into views itself. The interface got more simpler, we don't need a new hook here. So the "views_fieldrewrite" module is now small and clean. I get rid of evil eval(). Instead of that, there is a "file cache". The central idea of this is, that files containing classes that "decorates" normal handlers are being generated and saved within the files folder. It's ok in this case, cos the "handlers schema" is changing only when introducing new handlers, so we don't need to rebuild those files on every page load. The slow part, the generation of files is done after clear cache/install module and then there are only classes relying on inheritance, directly expanding original handlers, no call magic, no wrappers. This is also ready for the memcache too.

I would like to ask a question on memcache. What is more effective in terms of performance with memcache, to have many small files or one big?

wapnik’s picture

Status: Needs work » Needs review
wapnik’s picture

I've tried to put ale the code outside of Views, tried to make it more generic and here is what comes from it.

  • Decorator module is where all those file generating, caching takes place.
  • Views Decorator module deals with hook_views_handlers() and hook_views_data_alter() to determine the handlers that are going to be generated, uses Decorator for generating them and sends them back to Views.
  • Views Field Rewrite module implements a hook_views_decorators() for registering these "decorators" template handlers in Views Decorator.
bojanz’s picture

Status: Needs review » Fixed

wapnick has created his solution in cotrib, nothing else to be done here.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Nikdhil Mdohfan’s picture

What is the way to override views_handler_field_user_picture ?

I want t get picture as a link.

GaëlG’s picture

Issue summary: View changes

For those reading this queue, it's a problem I deal with in the Views navigation module.