Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Using classes instead of functions for plugins,nothing works

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
nicci
Smarty Rookie


Joined: 16 May 2016
Posts: 5

PostPosted: Mon May 16, 2016 11:45 am    Post subject: Using classes instead of functions for plugins,nothing works Reply with quote

I would like to use objects for plugins instead of global functions, and I'd like to more dynamically register / load them. Unfortunately Smarty makes this incredibly difficult and I seem to have run out of options. I'm hoping that I've missed something and am asking for help.

I first tried using the "register default plugin handler" but, this requires you to provide a callback that is not actually a callback. You cannot use objects in this, nor closures, only static or global functions. So that's useless to me.

Then I tried registering the plugin directly to a function on my main object, which would then dynamically map it to the right plugin object, like this;

$smarty->registerPlugin( 'block', 'form', [ $myObject, 'renderForm' ] );

The issue now is that Smarty seems to completely ignore the function name I provided in my callable (renderForm) and instead ALWAYS calls $object->render(). The way I have this set up, I require the custom function names, they cannot all be "render()".

Am I doing something wrong, or is Smarty really just ignoring the function and calling $object->render() regardless of the function name I provided? Is there really no way to do this without a) global functions, b) static functions or c) a method specifically named "render"?
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Mon May 16, 2016 12:59 pm    Post subject: Re: Using classes instead of functions for plugins,nothing w Reply with quote

nicci wrote:
I would like to use objects for plugins instead of global functions, and I'd like to more dynamically register / load them.
What could be any more dynamic, than "load only when they are needed" ?
And why objects? Are you a Java fanatic?
Quote:
Unfortunately Smarty makes this incredibly difficult and I seem to have run out of options. I'm hoping that I've missed something and am asking for help.

I first tried using the "register default plugin handler" but, this requires you to provide a callback that is not actually a callback. You cannot use objects in this, nor closures, only static or global functions. So that's useless to me.

You can, or at least, I were able to do so. With minimal code patching.
Back to top
View user's profile Send private message
nicci
Smarty Rookie


Joined: 16 May 2016
Posts: 5

PostPosted: Mon May 16, 2016 1:28 pm    Post subject: Reply with quote

I meant that I want to use objects AND dynamically load them. I know I can use global functions in subfolders and have Smarty find them for me, but it doesn't work that way with classes, you have to either manually register each one or use the default handler, as far as I can tell.

I would like to make use of class features in my plugins, and to also have them as part of my regular source tree, instead of a weird folder full of global functions on their own.

I don't think it's that strange, I suspect if Smarty was built from scratch today this is how they would design it.

What code did you patch? This doesn't seem like a very good alternative as it means I can't update Smarty without redoing my own patch. I was hoping there was some way to do this out of the box, I'm pretty surprised that there isn't.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Mon May 16, 2016 3:35 pm    Post subject: Reply with quote

You know, I was thinking about Smarty extensibility if it were rewritten to use classes.
If you want my opinion: It would be an unusable atrocity.
Either solitair-long constructions or ambiguous untraceable names.
There's no advantage to use classes where a simple function may suffice.
And even if classes were a thing, you would be bound by the interfaces, and random method calling will not be a thing either.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Mon May 16, 2016 3:35 pm    Post subject: Reply with quote

P.S.
I'm digging my patches but I have a work ongoing so it may take time.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Mon May 16, 2016 8:34 pm    Post subject: Reply with quote

This is a bug.
Once a template is compiled with a registered plugin which is an object it will use that method name if you later register other object with with different method.

Currently you must delete the compiled and cached template files manually if
you register an object which has changed method name.
I will try to fix this ASAP.
Back to top
View user's profile Send private message
nicci
Smarty Rookie


Joined: 16 May 2016
Posts: 5

PostPosted: Mon May 16, 2016 9:01 pm    Post subject: Reply with quote

AnrDaemon wrote:
There's no advantage to use classes where a simple function may suffice.


I'm sure they would provide a base class for each plugin type for you to extend. Meaning all the mess you refer to would not be an issue for the end user. Otherwise I doubt you would need anything in the constructor beyond what you need in the function, in fact you would need less because not everything would be available when it's first constructed. Then a simple call function on the object that takes in the currently relevant information (attributes, content, current template state with stack and such).

There are definitely things you could benefit from by having classes. Say you have a suite of HTML tags, they can inherit various basic functionality. Perhaps you want to use existing functionality for a plugin but decorate the input or output. You could split the "events" up in to more than one call, like open / body / close tag. I can think of lots of reasons why it would be handy. IMO it is also cleaner. Instead of passing all those params to an object you can access them through the base class in cleaner ways. It makes it easier to track the state of this plugin during open / repeat / close stages. You can use the stack to call on your custom functions on parent tags to make interaction between nested tags easier.

This is a bit moot as, it is what it is, but I have used other template engines that use classes to add extensions and it's very handy and very clean, and fits in much better with the rest of your system.

U.Tews wrote:
This is a bug.


Ohhhhhh! OK thank you so much, I will try that shortly!!
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Mon May 16, 2016 10:51 pm    Post subject: Reply with quote

I'm not talking about decoration and inheritance (note: inheritance is a bad practice in general).
I already said that interfaces should be provided, but what I'm talking about is not that.
What I'm talking about is usability.
How would you implement calling plugins from templates?
How would you implement the search and loading of them?
And please refrain from using terms "somehow", or "imagine".
Specific examples, please.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Mon May 16, 2016 11:55 pm    Post subject: Reply with quote

I seems to have deleted my experiments. :/
I'll try to get some patches up once [insert hope here] I throw away some of the current load.
Back to top
View user's profile Send private message
nicci
Smarty Rookie


Joined: 16 May 2016
Posts: 5

PostPosted: Tue May 17, 2016 12:39 am    Post subject: Reply with quote

AnrDaemon wrote:
I'm not talking about decoration and inheritance (note: inheritance is a bad practice in general).


How is inheritance a bad practice in general? It is one of the core features of object oriented programming, which most modern languages use extensively, and which PHP has worked very hard over the years to catch up with.

AnrDaemon wrote:
I already said that interfaces should be provided, but what I'm talking about is not that.
What I'm talking about is usability.
How would you implement calling plugins from templates?
How would you implement the search and loading of them?
Specific examples, please.


I gave plenty of examples of how one might use it, off the top of my head. In practice I'm sure there are many more. If you want implementation examples, look at Twig, which seems to be quickly becoming more popular than other PHP template engines. I actually really tried to switch to Twig because the back end is a lot nicer, but I didn't like the actual template syntax so now I'm trying to do my best to use Smarty in the way I want. A lot of Twig plugins are just simple closures (something Smarty also does not support) but it provides a lot of freedom to use classes for more advanced things than just simple functions and modifiers. Calling from templates? The template syntax does not need to change. I am happy with the Smarty template syntax as-is. Search and loading? There are plenty of ways. Class loaders, config files, factories, dependency injection, etc... My plan is to use plain old convention combined with a default handler and the class finder + loader I already use. Perhaps it sounds over complicated on paper but these are systems used constantly throughout our system and they actually make things much simpler once you're used to them. Usability? Again look at Twig. You can provide simple functions via closures, but if you want to go deeper you can use classes. PHP callables are meant to allow any of these - global function calls, static function calls, object method calls and closures. Twig supports all of these but unfortunately Smarty does not.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Thu May 19, 2016 2:01 pm    Post subject: Reply with quote

nicci wrote:
How is inheritance a bad practice in general? It is one of the core features of object oriented programming, which most modern languages use extensively, and which PHP has worked very hard over the years to catch up with.

You're confusing language functionality with usage practices.
You are not inheriting Smarty, nor are Smarty inheriting your project, to provide its services. You are embedding it into your project as an integrated byt still self-contained part.
Composition over inheritance.
nicci wrote:
I gave plenty of examples
I didn't see any code. May be I'm blind?
Twig is atrocious.
Back to top
View user's profile Send private message
nicci
Smarty Rookie


Joined: 16 May 2016
Posts: 5

PostPosted: Thu May 19, 2016 8:13 pm    Post subject: Reply with quote

No thanks. I didn't come here for advice and debate, I came here to have a question answered. You can go on assuming you know everything and I'm just going to continue doing my work. Later.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Thu May 19, 2016 8:43 pm    Post subject: Reply with quote

I don't know everything, that's why I'm asking questions.
They help me sharpen my knowledge.
I think I've narrowed my thoughts to make them readable on paper, thanks to your topic.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1785

PostPosted: Fri May 20, 2016 3:39 pm    Post subject: Reply with quote

Found the patched autoloader.
Looking for the rest.
Code:
--- Smarty/smarty-3.1.29/libs/Autoloader.php   2015-12-21 04:57:06.000000000 +0300
+++ Smarty/smarty-current/libs/Autoloader.php   2016-02-23 06:52:13.058207400 +0300
@@ -24,21 +24,21 @@
      *
      * @var string
      */
-    public static $SMARTY_DIR = '';
+    private static $SMARTY_DIR = '';
 
     /**
      * Filepath to Smarty internal plugins
      *
      * @var string
      */
-    public static $SMARTY_SYSPLUGINS_DIR = '';
+    private static $SMARTY_SYSPLUGINS_DIR = '';
 
     /**
      * Array with Smarty core classes and their filename
      *
      * @var array
      */
-    public static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
+    private static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
 
     /**
      * Registers Smarty_Autoloader backward compatible to older installations.
@@ -72,10 +72,9 @@
      */
     public static function register($prepend = false)
     {
-        self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR;
-        self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR :
-            self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR;
-        if (version_compare(phpversion(), '5.3.0', '>=')) {
+        self::$SMARTY_DIR = dirname(__FILE__);
+        self::$SMARTY_SYSPLUGINS_DIR = self::$SMARTY_DIR . "/sysplugins";
+        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
             spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
         } else {
             spl_autoload_register(array(__CLASS__, 'autoload'));
@@ -90,35 +89,15 @@
     public static function autoload($class)
     {
         $_class = strtolower($class);
-        $file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
-        if (strpos($_class, 'smarty_internal_') === 0) {
-            if (strpos($_class, 'smarty_internal_compile_') === 0) {
-                if (is_file($file)) {
-                    require $file;
-                }
-                return;
-            }
-            @include $file;
-            return;
-        }
-        if (preg_match('/^(smarty_(((template_(source|config|cache|compiled|resource_base))|((cached|compiled)?resource)|(variable|security)))|(smarty(bc)?)$)/',
-                       $_class, $match)) {
-            if (!empty($match[3])) {
-                @include $file;
-                return;
-            } elseif (!empty($match[9]) && isset(self::$rootClasses[$_class])) {
-                $file = self::$rootClasses[$_class];
-                require $file;
-                return;
-            }
+        if (isset(self::$rootClasses[$_class])) {
+            $file = self::$SMARTY_DIR . "/" . self::$rootClasses[$_class];
         }
-        if (0 !== strpos($_class, 'smarty')) {
-            return;
+        elseif (strpos($_class, 'smarty_') === 0) {
+            $file = self::$SMARTY_SYSPLUGINS_DIR . "/{$_class}.php";
         }
-        if (is_file($file)) {
-            require $file;
-            return;
+
+        if (isset($file) && is_file($file)) {
+            return include_once $file;
         }
-        return;
     }
 }
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP