Tuesday, July 17, 2018

Ugly hack series Ep 1

Ugly hack series Ep 1



Development for me is an art. I like the structures and the whole design. One particular difference between normal-people art and tech art is the limitations. To workaround those limits you apply hacks sometimes. Well, they say its only the matter of time. And with that I agree. But time is the one scarce resource we dont have. So we hack.


Ive seen many of them through my experience. Some core hack here and there (not me, I swear), some contrit patch and the total negligence of Drupal ecosystem.

Then there are the low level hacks, such as saving temporary variables in the global scope. Or saving them in session. Which hopefully we all know is a security issue.

But today I mastered myself to a new level. (Im not proud at all.) Sometimes you have global alters that takes a certain modification on a data. The key here is that its global, so applied without any context. Thats nice, because you can alter the system from a single point (yeah, I can hear your inner voice: of failure). Oh the other hand you dont have context and when you alter you possibly cut the flexibility from other behaviors. My case is around the format_username() call. This function gets the formatted username, which is alterable by hook_username_alter(). I needed however the username in a different format - through the same format_username() call - which I didnt owned. So somehow I had to generate different output from the same function without context?

If you have enough willpower read no further and think about what would you do in this case. (Image is only for distracting you.)


Now my hack is actually using the context. How? Let me introduce: debug_backtrace(). This call gives you the call stack youre in at the moment:

$call_stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);


I knew that the different output is only needed when its called through a special function, lets call him: collect_special_usernames(). I need to filter through the call stack to see if it was the caller:

$call_stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$caller_is_found = array_filter($call_stack, function($item){
return $item[function] == collect_special_usernames;
});


Here $caller_is_found will be empty if my function in interest wasnt there - and will contain that item if it was. To make it handy we can create a wrapper:

function is_called_through($function_name) {
$call_stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

$caller_is_found = array_filter($call_stack, function($item){
return $item[function] == $function_name;
});

return !empty($caller_is_found);
}


At the end I managed to find a hook to fulfill my needs, so I didnt have to apply this hack. But still, has its own charm, dont you think?

---

Please, share your favorite ugly hack.

Peter

go to link download