2

I'm trying to update my extension for Joomla 4 alpha. It adds a button in the editor that calls a dialog file in a popup window. The link is triggered like this:

$button->set('link', '../plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name);

This works fine in Joomla 3.x, but in Joomla 4, the link in the button is transformed like this:

https://mydomain.com/administrator/../plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=jform_articletext

It adds administrator/ in front of the link. Since insertmystuff is not in the administrator folder but in the plugins folder, the link is broken.

How do I change the code in such a way that it doesn't add administror/ ? I tried with this as well:

$button->set('link', '../../plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name);

But that creates a 404 and it redirects to the home page in the popup window instead.

Any ideas? Thanks beforehand. :-)

Update: The complete code of the file is like this:

<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport( 'joomla.plugin.plugin' );

class plgButtonInsertS3Media extends JPlugin
{

    function plgButtonInserthtmlex( &$subject, $config )
    {
        parent::__construct( $subject, $config );
    }

    function onAfterInitialise()
    {
    }

    function onDisplay($name) // $name: Editor Element ID
    {
        $mainframe = JFactory::getApplication();

        $button = new JObject();

        $doc = JFactory::getDocument();
        $template = $mainframe->getTemplate();
        if ( $mainframe->isSite() ) {
            $enable_frontend = $this->params->get("enablefrontend");
            if ( $enable_frontend == 0) {
                return $button;
            }
        }

        $lang = JFactory::getLanguage();
        $lang->load('plg_editors-xtd_inserts3media', JPATH_SITE . DS . 'administrator');
        $this->loadLanguage();


        $js = "function S3Media_InsertCallback( editor, result )
                {
                if( result ) {
                    jInsertEditorText(result, editor);
                    }
                }";

        $doc->addScriptDeclaration($js);

        $css = " .icon-InsertS3MediaButton { background: url(../plugins/editors-xtd/inserts3media/insert_s3media/editor_button.png) 100% 0 no-repeat; } ";

        $doc->addStyleDeclaration($css);

        $button->set('modal', true);
        $button->set('class', 'btn');
        $button->set('text', 'Insert S3 Media');
        $button->set('name', 'InsertS3MediaButton');
        $button->set('link', '../plugins/editors-xtd/inserts3media/insert_s3media/s3plugin_dialog.php?e_name=' . $name);
        $button->set('options', "{handler: 'iframe', size: {x:window.getSize().x-100, y: window.getSize().y-100}}");

        return $button;
    }

}

?>

UPDATE: I tried all constants, they keeps adding domainname/administrator/in front of the constant and the part in quotes. I even tried an absolute path to the current root, it still adds that stuff. What bugs me is that it works fine in Joomla 3.9.2

UPDATE 2: Additional info The plugin inserts shortcode into the editor, generated by the value of the fields in the popup window, typed in by the user and/or retrieved from the database. The output of the shortcode in the frontend is handled by the component.

3

1 Answer 1

3

You should try to define the path with using Constants:

$button->set('link', JPATH_ROOT . '/plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name); 

or:

$button->set('link', JPATH_SITE . '/plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name); 

You can also try with:

$button->set('link', JPATH_PLUGINS . '/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name); 

you have to check if there is double slash or full url path is created then you just delete the slash before the path string ‘/‘ like this:

$button->set('link', JPATH_PLUGINS . 'editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name); 

Sometimes also works if you only just delete the slash from the beginning of the path and without a constant, do it like:

$button->set('link', 'plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name); 

And one more version which works if you are calling the path from admin, simply again with one slash:

$button->set('link', '/plugins/editors-xtd/insertmystuff/insert_mystuff/mystuffplugin_dialog.php?e_name=' . $name);

It always depends on where the path is called from. Since I cannot fully see your code that is why I gave many options to try. This is how we always call path nowadays. One of them should work.

UPDATE - ON JOOMLA 4 AND LINKS

I created different kind of link examples on my frontend in Joomla 4 to test what it gives back. So these are the links:

$link1 = '/editors-xtd/insertmystuff/insert_mystuff';
$link2 = JPATH_ROOT . '/editors-xtd/insertmystuff/insert_mystuff';
$link3 = JPATH_PLUGINS . '/editors-xtd/insertmystuff/insert_mystuff';
echo '<br>This is $link1: '  . $link1;
echo '<br>This is $link2: ' . $link2;
echo '<br>This is $link3: ' . $link3; die;

And this is what I got back on the frontend on cassiopeia template opening page:

This is $link1: /editors-xtd/insertmystuff/insert_mystuff

This is $link2: G:\websites\joomla4/editors-xtd/insertmystuff/insert_mystuff

This is $link3: G:\websites\joomla4\plugins/editors-xtd/insertmystuff/insert_mystuff

So, you can see what the different path values are given back to me on Joomla4 front-end (in localhost so it could be sometimes different on the web). There is no any problem with Joomla4 (alpha) link path creation. Thus we have to investigate and try the different path definitions a bit further on buttons.

UPDATE 2 - POSSIBLE WORKAROUND

I also do not see yet where this added path defined, actually it is adding a JPATH_ADMINISTRATOR constant to your given link always. It would take more time to check this why.

THE SOLUTION

At the moment I see one sensible workaround of your problem and it is based on how other editors-xtd plugins are defining their links on their own buttons. It looks like that it's the more Joomla standard way. For example the CMS image button link:

$link = 'index.php?option=com_media&amp;tmpl=component&amp;e_name=' . $name . '&amp;asset=' . $asset . '&amp;author=' . $author;

or the pagebreak:

$link = 'index.php?option=com_content&amp;view=article&amp;layout=pagebreak&amp;tmpl=component&amp;e_name=' . $name;

And $button->set('link', $link);

Well, they just simply create it this way: $button->link = $link; but it does not matter.

So this is what I see as a workable solution on this suddenly if you reformulate your link. If it could work for you:

for this link approach you should just move your plugin popup layout (dialog layout) file: mystuffplugin_dialog.php to yourjoomla/administrator/components/com_content/tmpl/article folder and your button link should be rewritten to:

$link = 'index.php?option=com_content&amp;view=article&amp;layout=mystuffplugin_dialog&amp;tmpl=component&amp;e_name=' . $name;

And the button link set obviously: $button->set('link', $link);

Try this and we will see how it goes.

MORE APPROPRIATE SOLUTION

You do not have to! place your plugin layout file in the com_content folder directly, with that we just tried that the above path structure is working in your 10 years old plugin button object link. As I wrote in my comment, With the above path method, you can target and get your layout from other directories too. Most importantly there is a layouts folder in Joomla and in that folder at: yourjoomla/layouts/joomla/content you can place your plugin modal layout file too and you should be able to call that with the above path structure method. Try that.

Nowadays we call layout files with the following method if for example my layout file is in my plugin folder and it's called for example mylayout.php file:

$mypathtoLayout = JPATH_ROOT . 'plugins/com_whatever/my_genius_plugin/layouts/'
$layout      = new JLayoutFile('mylayout', $mypathtoLayout);

// and we just render and echo the $layout
echo $layout->render();

So there are a lot of possibility of adding layout to anything in Joomla.

And just because of the “very smart kids” around here (they need at least 10-15 years more in this field), I also place the link to Joomla documentation about layout sharing in Joomla across extensions. https://docs.joomla.org/J3.x:Sharing_layouts_across_views_or_extensions_with_JLayout

I also would like to highlight one sentence from this doc:

”Passing in a non-empty base path allows accessing and STORING layout files ANYWHERE on the site directory structure, for instance:...”

And another great Joomla doc about the layout system and how and when to use them and when not to: https://docs.joomla.org/J3.x:JLayout_Improvements_for_Joomla!

And one more relevant thing about using JObject at all for buttons in plugins when you are now building an editor plugin for example, it is a BIG NO! Why? The notice about JObject getting deprecated started back in 2016 (at least). Making a button in layouts should be done with using Toolbar object (or new stdClass(); ), not JObject and not CMSObject! Link to this issue from 2016: https://github.com/joomla/joomla-cms/issues/12449

So giving an advice in 2018-19 on how to use a JObject in an editor plugin is just dumb as hell, as we all are usually. And we could continue this subject on and on but this question was just about a fast repair of a link on a button in an old editor plugin. So we can live with that. :)

JOOMLA BUTTON PLUGIN (EDITOR-XTD PLUGIN) - JOOMLA 4 - A NEVER-ENDING STORY

Now, of course I checked a bit more the Joomla 4 editor-xtd button plugin creation and I can confirm that it is just horrible. It's just a thing that Joomla core plugins use CMSObject (deprecated) and JObject (also deprecated) for these editor-xtd plugin creations, but on the top of that, if you just define a $link to your layout which is sitting in the site (not in the administrator part of your site) it is just impossible. Since the $button->link in the button object and in Modal object is created the way that in any case the defined final $link will be concatenated with 'Uri::base()'. You cannot avoid that. Here is how a button link is defined finally if you try to give a path to your layout:

$link    = ($button->get('link')) ? Uri::base() . $button->get('link') : null;

And that is why @Rudolf has heavy headaches many days ago. He just wanted to refresh his plugin and tried to add his button to an editor with a "button plugin". Yes, sure, good luck for that :)

Changing the JObject to an anonymous PHP Object is easy and that way it won't be deprecated for a long time. It does not give any advantage in function but at least your plugin will not go break on JObject after a time. The $button object only use a get() function, nothing else, so if you just define a button this way, you cannot really go into trouble:

        $button = new Class
        {
            public function get($property, $default = null)
            {
                if (isset($this->$property))
                {
                    return $this->$property;
                }

                return $default;
            }
        };

        // $link = 'index.php?option=com_content&amp;view=article&amp;layout=mylayout&amp;tmpl=component&amp;'
        // . Session::getFormToken() . '=1&amp;editor=' . $name;
        
        $button->modal = true;
        $button->class = 'btn btn-secondary mybutton';
        // $button->link = $link; // this is the problematic part
        $button->onclick = "mybuttonclick();";
        $button->text = Text::_('MY BUTTON MINE');
        $button->name = 'file-add';
        $button->options = array(
            'height'     => '300px',
            'width'      => '800px',
            'bodyHeight' => '70',
            'modalWidth' => '80',
        );

        return $button;

This is the very easy part. But if you define a $link in the editor-xtd plugin, you can only go to the administrator directory for your Modal layout. So this is quite a shame for a button plugin in Joomla in 2019. It’s not a bug and it’s also true that it can be due to security reason just to not let people to call a button or a modal from external sources (as probably many have done that) and the site can be hacked via this button path. However, in this fashion, It only can work well, if someone really create a component (totally redundantly for a simple plugin), or create an ajax call to a Layout file and can call it that way from almost anywhere (at least we hope so).

ENDING THE LONG STORY

I don't think anybody will read this long story but anyway. As I see Rudolf is a quite busy guy, so giving him an advice to create a component would not be too fair with him, as he just wanted to get his button back, nothing else ;) which has been ticking and clicking in the last ten years. And it's true that he has a component too and he could create a view for that and a layout in the admin part of that component, but He is not a Joomla extension developer to waste his time for that. Finally I had to realize that the long story can be solved (now it's obvious) with few lines of jQuery code and Rudolf's Modal layout can stay at the same place in the plugin folder where it was in the last decade or so. So in the main plugin file a short jQuery should be inserted and the whole story is closed. And he already has a short javascript inserted in his code so nothing new here. This is how the onDisplay function should start:

public function onDisplay($name)
    {

        // we have to add this short script here
        $document = JFactory::getDocument();
        $document->addScriptDeclaration('
        
        $(document).ready(function(){
        
            alert("This script is running well");
            let myurl = "/plugins/editors-xtd/editorextdmine/layouts/mylayout.php";
            let dataframeval = \'<iframe class="iframe" src = "/plugins/editors-xtd/editorextdmine/layouts/mylayout.php" name = "MY BUTTON MINE" height = "300px" width = "800px" ></iframe >\'           
            
            $("#MYBUTTONMINEModal").attr({
                                    "data-url": myurl,
                                    "data-iframe": dataframeval ,
                                    });           
          
        });          
                
        ');

This short code actually changing two iframe attributes which is quite wrongfully generated by the Joomla Button Modal layout file and that caused this stupid problem. The button #id and the url value has to be changed to customized values and that is about it.

And the usual visual just to show that this script is working in Joomla 4 Modal loading in the editor with a custom button, loading the layout from the plugin's layouts folder:

enter image description here

4
  • In Joomla 3.9 I get: mydomain.com/plugins/editors-xtd/inserts3media/insert_s3media/… <br> With Joomla 4 using /plugins/editors-xtd/inserts3media/insert_s3media/s3plugin_dialog.php?e_name=' . $name I get this: mydomain.com/administrator//plugins/editors-xtd/inserts3media/… <br>(taken from the source code, because the button doesn't allow to show it in the statusbar
    – Rudolf B
    Commented Feb 2, 2019 at 16:19
  • @RudolfB - Just updated with a possible workaround. It looks like Joomla 4 will not like the old direct links to plugin files as you gave it earlier. It has to be reworked.
    – Zollie
    Commented Feb 2, 2019 at 18:36
  • @RudolfB - I got you, but the point is that now you know that this is the workable way of how to build and call the path correctly for a button to your layout, it works from Joomla 3 and 4 too. Then from now you can target almost any forder with this method. I could do that quite fast but I am not the programmer of your plugin, you see and I also cannot try different folder paths for your plugin button since I really do not know anything about your plugin dependencies, only that it has a button which opens something. So I can show you workable directions only and how I would approach that.
    – Zollie
    Commented Feb 3, 2019 at 12:26
  • You're spot on: the plugin bit to add shortcode in the editor was developed in 2010 by a hired programmer. It worked ever since from Joomla 1.5 to 3.9.2 (with some minor changes, like changing deprecated functions) Still, JCE editor doesn't put stuff in that core folder, so I'm hesitant to take that road. But I'll take your hint and look into better methods for the popup. Thanks for your time.
    – Rudolf B
    Commented Feb 3, 2019 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.