News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

integrate hooks doesn't support classes - SMF 2.0

Started by tinoest, September 26, 2012, 04:59:41 PM

Previous topic - Next topic

tinoest

I'm not sure if this is an error or just the nature of SMF 2.0

It seems that SMF 2.0 doesn't support classes when you integrate a hook , it will often check if the function_exists , which doesn't work with the class format for php i.e ClassName::FunctionName , I don't see why method_exists isn't an option where you place a call to a function like the following


function check_function_exists ( $functionName ) {
  $ret = explode ( '::' , $functionName );
  if(count($ret) = 2) {
    return method_exists($ret[0] , $ret[1]);
  } else {
    return function_exists($functionName);
  }
}



I haven't tested the above btw just sudo coded it whilst typing this topic.

Suki

That has been already fixed for 2.1.

For 2.0 you can always use wrapper functions:

function wrapper_for_static_method(){ClassName::FunctionName();]
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Arantor

That would be an issue if SMF actually used function_exists, but it doesn't.

foreach ($functions as $function)
{
$function = trim($function);
$call = strpos($function, '::') !== false ? explode('::', $function) : $function;

// Is it valid?
if (is_callable($call))
$results[$function] = call_user_func_array($call, $parameters);
}


There are mods that already use static methods of a class to do their job - SimpleSEF for example.

tinoest

Quote from: Suki on September 26, 2012, 05:23:07 PM
That has been already fixed for 2.1.

For 2.0 you can always use wrapper functions:

function wrapper_for_static_method(){ClassName::FunctionName();]

Hi Suki,

That's essentially what I did, glad to hear its fixed.


tinoest

Quote from: Arantor on September 26, 2012, 05:28:10 PM
That would be an issue if SMF actually used function_exists, but it doesn't.

foreach ($functions as $function)
{
$function = trim($function);
$call = strpos($function, '::') !== false ? explode('::', $function) : $function;

// Is it valid?
if (is_callable($call))
$results[$function] = call_user_func_array($call, $parameters);
}


There are mods that already use static methods of a class to do their job - SimpleSEF for example.

If you integrate a profile template / option it does.... in Profile.php I believe it was.

Arantor

Are you talking about using a hook or integrating templates? The two are very different things.

Hooks can quite happily be class methods as demonstrated.

Template functions cannot be made into class methods, no, because of one of the other requirements - it's not just about the function_exists() call, it's the fact that if you set up a sub-template as 'main' (as is default), it's going to look for template_main() to call, and if you use layers, it'll look for template_layer_before and template_layer_after, which is not possible to sanely declare anyway in the construct that currently exists, though I suppose you could declare 'class::method' and call 'class::method_before' and 'class::method_after'.

tinoest

Quote from: Arantor on September 26, 2012, 05:42:05 PM
Are you talking about using a hook or integrating templates? The two are very different things.

Hooks can quite happily be class methods as demonstrated.

Template functions cannot be made into class methods, no, because of one of the other requirements - it's not just about the function_exists() call, it's the fact that if you set up a sub-template as 'main' (as is default), it's going to look for template_main() to call, and if you use layers, it'll look for template_layer_before and template_layer_after, which is not possible to sanely declare anyway in the construct that currently exists, though I suppose you could declare 'class::method' and call 'class::method_before' and 'class::method_after'.

To clarify, I was adding an additional option to the profile areas using this method / hook integrate_profile_areas which after a while of debugging I discovered it was due to me writing it as a class an not a function.

It might be a lack of clear documentation issue, more than anything else to be honest.

Arantor

Share the code, that'll help nail down the problem faster than anything.

tinoest

function ProfileAddition(&$profile_areas) {{{

  global $txt;

  $profile_areas['info']['areas']['profileaddition'] = array(
    'label' => 'mylabel' ,
    'file' => 'File.php' ,
//    'function' => create_function(null ,  'MyClass::MyFunction();'),    // Doesn't work as it searches for a lamba_x template
//    'function' => 'MyClass::MyFunction', // Also doesn't work , says not allowed to access this area
      'function'=> 'MyFunction', // This does work
    'permission' => array ( 'own' => 'profile_view_own' , 'any' => 'profile_view_any' , ) ,
  );

  }}}


INSERT INTO `smf_settings` (`variable`, `value`) VALUES
('integrate_pre_include', '/var/www/smf/Sources/File.php'),
('integrate_profile_areas', 'MyClass::ProfileAddition');


I have quickly done essentially what I was trying to do with the parts that don't work as expected commented.

It's line 441 where it falls over for me, in Sources/Profile.php

Arantor

Awesome, so your assertion that hooks don't support classes is still wrong.

The registration of hooks works and where you actually call hooks will work with a class. What you're trying to do is NOT a hook. It needs changes elsewhere in Profile.php, and similarly in Admin.php where the same problem will occur.

tinoest

Quote from: Arantor on September 27, 2012, 02:50:09 PM
Awesome, so your assertion that hooks don't support classes is still wrong.

The registration of hooks works and where you actually call hooks will work with a class. What you're trying to do is NOT a hook. It needs changes elsewhere in Profile.php, and similarly in Admin.php where the same problem will occur.

Although it is still defined as a hook on the following page:

http://wiki.simplemachines.org/smf/Integration_hooks

I will admit , I should of been clearer, in some instances it doesn't suppose classes, but respectfully there is no need for the aggression.

Arantor

Respectfully, there is no aggression. You're the one calling it a bug, except that what you've called a bug is not a bug.

This topic is called 'integrate hooks doesn't support classes' - except as *proven*, it does.

The fact you're trying to use something that isn't an integration hook with a class function is a separate bug entirely.

Hooks can call static class members. The menu initialisation code can't handle that. But that's NOT a problem with the hooks system. It's a problem with the menu code. Such things are important because as stated, there would have been a lot of time wasted chasing down a bug that doesn't exist because the symptoms weren't actually explored in depth.

tinoest

Quote from: Arantor on September 27, 2012, 02:55:40 PM
Respectfully, there is no aggression. You're the one calling it a bug, except that what you've called a bug is not a bug.

This topic is called 'integrate hooks doesn't support classes' - except as *proven*, it does.

The fact you're trying to use something that isn't an integration hook with a class function is a separate bug entirely.

Hooks can call static class members. The menu initialisation code can't handle that. But that's NOT a problem with the hooks system. It's a problem with the menu code. Such things are important because as stated, there would have been a lot of time wasted chasing down a bug that doesn't exist because the symptoms weren't actually explored in depth.

So what it comes down to is it is a bug in the documentation rather than SMF itself.

Arantor

No, it isn't that either.

The documentation says the hook can call a static function. Which is absolutely correct.

The documentation does not - not should it - cover what you need to do in that function. If you're capable of writing code that works with hooks, you probably should be looking in Profile.php to see how to declare it and what changes are required - where you would have seen the fact it doesn't support classes.

What should be done, really, is the profile code and admin code should be updated to handle calling classes.

emanuele

Just for the record, the function name is used also as sub_template (not that this stops from allow using static functions from the menu, worst case the sub_template should be assigned "by hand").


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

tinoest

Quote from: Arantor on September 27, 2012, 03:02:28 PM
No, it isn't that either.

The documentation says the hook can call a static function. Which is absolutely correct.


Although not in all instances , as I thought by definition a static function was Class::Function

Or is my understanding incorrect?

Arantor

-sigh-

Your understanding is way too broad.

The hook's functionality is SOLELY related to actually *calling the function*. Not what you do INSIDE that function.

call_integration_hook can call a static method. As demonstrated.
The item you add to $profile_areas from inside that static method cannot itself be a method of a function. Meaning that while you can create a class and have that hook call your class, you currently have to make the actual page that does the real work be a custom function.

There are only so many ways I can explain what the problem is here.

tinoest

Quote from: Arantor on September 27, 2012, 03:29:17 PM
-sigh-

Your understanding is way too broad.

The hook's functionality is SOLELY related to actually *calling the function*. Not what you do INSIDE that function.

call_integration_hook can call a static method. As demonstrated.
The item you add to $profile_areas from inside that static method cannot itself be a method of a function. Meaning that while you can create a class and have that hook call your class, you currently have to make the actual page that does the real work be a custom function.

There are only so many ways I can explain what the problem is here.

Ok so we both agree on something. This can be moved to where ever it is required.

In future , I shall be more specific about the issue.

Arantor

I'm not sure we agree because I'm not entirely sure you understand what the problem is... but it is in the right place.

Arantor

No changes are actually required in SMF at this time for this issue, at least nothing we can do that would be a worthwhile change without causing a *lot* of regression testing, all because of avoiding manually updating $context['sub_template'] inside a class method.

Advertisement: