?
avatar dmz9
dmz9
14 Sep 2017

Here is the code in com_ajax/ajax.php

$group      = $input->get('group', 'ajax');
JPluginHelper::importPlugin($group);
$plugin     = ucfirst($input->get('plugin'));
$dispatcher = JEventDispatcher::getInstance();

what does it do : gets plugins' group from URL and loads it. then it emits an event.

whats wrong with that:

  1. lets say i have a plugin assigned to group "vmshipment", and i need to do an ajax call to it. doesnt matter why - i need to do it, period.
  2. url for the call is like this one: "/index.php?option=com_ajax&plugin=MYPLUGIN&format=json&group=vmshipment"
  3. calling to exact plugin (i have already mentioned it: look at plugin=MYPLUGIN) - loads all the group (vmshipment)
  4. default vmshipment plugin (which is included in package virtuemart 3) has some constants, which are not supposed to exist, when plugin is loaded this way.
    so in the end i get fatal error : undefined constants (DS) and (JPATH_VM_PLUGINS)

this happens just because loading logic is wrong: the com_ajax code loads all the plugins of a group at once and try to emit an event for all of them.
instead, i expected only MYPLUGIN to be loaded.
and that is achieved just by adding some code in importPlugin call like this:

JPluginHelper::importPlugin($group, $input->get('plugin', null));

this loads only my plugin and nothing else (or all the group, if 'plugin' key not found in $input, because the default is 'null')

==============

here are some errors produced during the ajax call

Notice: Use of undefined constant JPATH_VM_PLUGINS - assumed 'JPATH_VM_PLUGINS' in ****/plugins/vmshipment/weight_countries/weight_countries.php on line 24

Notice: Use of undefined constant DS - assumed 'DS' in ****/plugins/vmshipment/weight_countries/weight_countries.php on line 24

Warning: require(JPATH_VM_PLUGINSDSvmpsplugin.php): failed to open stream: No such file or directory in ****/plugins/vmshipment/weight_countries/weight_countries.php on line 24

Warning: require(JPATH_VM_PLUGINSDSvmpsplugin.php): failed to open stream: No such file or directory in ****/plugins/vmshipment/weight_countries/weight_countries.php on line 24

Fatal error: require(): Failed opening required 'JPATH_VM_PLUGINSDSvmpsplugin.php' (include_path='.:/opt/php56/share/pear:/opt/php56/share/php/php') in ****/plugins/vmshipment/weight_countries/weight_countries.php on line 24

avatar dmz9 dmz9 - open - 14 Sep 2017
avatar joomla-cms-bot joomla-cms-bot - labeled - 14 Sep 2017
avatar franz-wohlkoenig franz-wohlkoenig - change - 14 Sep 2017
Priority Urgent Medium
avatar SharkyKZ
SharkyKZ - comment - 15 Sep 2017

You're getting these errors because VmConfig isn't loaded. VM plugins assume it would be loaded (they're not designed to be used outside of VM). VM recently added a system plugin which loads VmConfig but only on Joomla updater pages. You could ask VM developer to add AJAX page support or make your own plugin.

avatar joomla-cms-bot joomla-cms-bot - close - 15 Sep 2017
avatar franz-wohlkoenig franz-wohlkoenig - change - 15 Sep 2017
Status New Closed
Closed_Date 0000-00-00 00:00:00 2017-09-15 06:30:46
Closed_By franz-wohlkoenig
avatar joomla-cms-bot
joomla-cms-bot - comment - 15 Sep 2017
avatar franz-wohlkoenig
franz-wohlkoenig - comment - 15 Sep 2017

as stated above closed as no Core-Issue.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/17955.

avatar dmz9
dmz9 - comment - 15 Sep 2017

@SharkyKZ its not just about VM plugin.
i do design my plugin, does not matter if it belongs to "VM group" or not, and i can make it support ajax for my own special needs, which could not require any virtuemart code to work. i just need to save extra data, thats all.
and i expect native joomla ajax to work, instead, i get errors which are related to 3-rd party system (yeah. plugin written by vm devs).
if that would be another plugin group - what does it changes? still, with this code - successful ajax call via com_ajax relies on the rest of the plugin group.

on the other hand - for now i cant assign a plugin into 2 or more different groups - i would do it, just to make it support ajax, but joomla is not flexible enough

so basically you ask me to find workaround for this case and do not use built-in ajax functions.
and what workaround would that be? split plugin functionality into 2 plugins, and add "ajax" version just for supporting native mechanics?

resuming: for now built-in ajax requires all the plugins of a custom group (not "ajax" one) to be written with ajax support (meaning: not having errors when loaded with plugin loader). thats not how you develop stuff, its just totally wrong.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/17955.
avatar Bakual
Bakual - comment - 15 Sep 2017

First, let me clarify that the plugin argument in the request doesn't refer to your specific plugin, but to the plugin event that should get triggered. Sp plugin=foo will trigger the onAjaxFoo event and all loaded plugins with such a method can respond to it.

There is no API to load a single specific plugin. The plugin architecture doesn't work that way (and should not).

The issue you have is not related to how com_ajax works. It's related to how the vm plugins are written. If they would first check if VmConfig is loaded (which would be good practice), then that issue wouldn't exist.

avatar dmz9
dmz9 - comment - 15 Sep 2017

@Bakual so, in other words, parameter "plugin" it not the parameter "plugin" and should be renamed into "eventName" or just "event".
so simple: it does not belong to one particular plugin, and could be responded by any plugin. so it's not the one exact plugin name to "load and respond" , its event name.
this is the problem i believe - unexpected behavior.

edit: the part about "not enough checks in 3-rd party plugins" - so true.

avatar Bakual
Bakual - comment - 15 Sep 2017

n other words, parameter "plugin" it not the parameter "plugin" and should be renamed into "eventName" or just "event".

From todays point of view, it's not named ideally. Back then, there was no group argument, you simply had module or plugin. As it would be a B/C break to change it, nobody did (personally I think it's not worth the break).

so simple: it does not belong to one particular plugin, and could be responded by any plugin. so it's not the one exact plugin name to "load and respond" , its event name.

Yes, any loaded plugin can respond to it. It's not even restricted to plugins of the specified group. I think at least system plugins are loaded as well at this point.
Exactly how our plugins are supposed to work - caller shouldn't be aware of the listeners.

avatar dmz9
dmz9 - comment - 15 Sep 2017

@Bakual

From todays point of view, it's not named ideally. Back then, there was no group argument, you simply had module or plugin. As it would be a B/C break to change it, nobody did (personally I think it's not worth the break).

naming stuff is the second hardest thing in development. (and every joke has a bit of joke.)

Yes, any loaded plugin can respond to it. It's not even restricted to plugins of the specified group. I think at least system plugins are loaded as well at this point.
Exactly how our plugins are supposed to work - caller shouldn't be aware of the listeners.

thats very cute when people follow the patterns ).

let i describe another way:
i have an exact request
i expect exact stuff to be loaded in backend
i expect plugin gives me response which is totally related to the request

now keeping in mind - i talk about ajax stuff (not regular frontend)

so there are 2 ways to create response in backend :

  1. load every part of the system to create response
    pros: no problems in getting any data.
    cons: it's slower
  2. or load some required parts of the system and create response
    pros: it's faster
    cons: everything can be broken if all the dependencies are not resolved and loaded before

this issues is about 2-nd part - framework can not resolve dependency and load VM core before plugin because it does not know how to do it.

since devs can write plugins depending on modules which depend on components depending on another components - there should be framework dependency resolver, which helps to load all the dependency tree before it starts to create the response in a plugin.

as i can see - it is not handled in this way, it's not dependency resolver, it's event based system.
and in event based system listeners do not know about each other - thats correct too.
the framework just loads some bunch of plugins of some kind (group!) blindly, not trying to understand what dependencies do they have.

i have worked with systems which follow case 1 - slower but i get what i want and not trying to workaround native stuff.
as a positive example - take a look at wordpress built-in rest api.
easy as a cake - register url, register handler - do the job.

avatar SharkyKZ
SharkyKZ - comment - 16 Sep 2017

Just to be clear, I'm not disagreeing, I just wanted to point out you were getting errors because of VM.

As others have said, making a change here could be a B/C break. But a parameter to import only single specified plugin can be added without trouble.

Add a Comment

Login with GitHub to post a comment