2

When a component is installed, it seems that until the user updates the configuration (using the "Options" button) a request to get the component parameters from Joomla returns an essentially empty object. The request:

$params = Joomla\CMS\Component\ComponentHelper::getParams('com_example);

results in a $params object that does not give values for $params->get('parmname'). It seems that the XML (config.xml) is not used during installation to create default parameters, but is only used when the user updates the "options".

Unfortunately, creating a new Registry object and using the method loadFile on config.xml does not produce a usable parameters object either. So a component that relies on parameter values (defaults will do until the user chooses something else) does not work on first installation.

Have I misunderstood something? Is there a solution to this?

3

It does seem that nobody has a solution to this issue based on a method within Joomla. The use of code in the script file that duplicates in different form the XML of config.xml is a work around. That is OK so far as it goes but it is clearly not ideal to have the same information in two different places. Especially in two different formats. It is almost certain to lead to inconsistencies sooner or later.

It is possible in a relatively few lines of code to turn the config.xml file into a Registry object, similar to the one that would be obtained from "getParams". It's here written as static methods within a utility class. Once you have a Registry object, you can obtain the JSON to store in the extension table by simply coercing the object to a string by putting (string) in front of it.

use Joomla\Registry\Registry;

public static function getParamsFromConfig($element) {
    $params = new Registry();
    $xmldata = simplexml_load_file(JPATH_ADMINISTRATOR . '/components/' . $element . '/config.xml');
    $paramarray = array();
    self::addLayerToParams($paramarray, $xmldata);
    $params->loadString(json_encode($paramarray));
    return $params;
}

private static function addLayerToParams(&$paramarray, $xmldata) {
    if ($xmldata->count()) {
        foreach ($xmldata->children() as $child) {
            self::addLayerToParams($paramarray, $child);
        }
    }
    if ('field' == $xmldata->getName()) {
        $paramarray[(string) $xmldata['name']] = (string) $xmldata['default'];
    }
}

I guess there must be code somewhat similar to this somewhere in com_config but so far as I can see, it is not readily accessible.

So far, I haven't explored the related question of how to deal with the situation where a new release of the component changes config.xml.

The code could be improved by adding error handling in case of mistakes in the XML of config.xml.

0

The key thing in the code in the first answer that doesn't want to display is this:

if ($type === 'install')
    {
        // Install the global extenstion params.
        $db    = JFactory::getDbo();
        $query = $db->getQuery(true);
        // Field to update.
        $fields = array(
            $db->quoteName('params') . ' = ' . $db->quote('{"authorName":"Your Name","authorEmail":"Your email","your config.xml param":"your config.xml param value"}'),
        );
        // Condition.
        $conditions = array(
            $db->quoteName('element') . ' = ' . $db->quote('com_mycom')
        );
        $query->update($db->quoteName('#__extensions'))->set($fields)->where($conditions);
        $db->setQuery($query);
        $allDone = $db->execute();

    }
0

It looks like your installer script is missing a line to store the global extension params. Is this Joomla 3 or 4?

----- Adding to answer

Here's an example of code from one of my components built using Joomla Component Builder.

Assuming your component is called mycom In your mycom.xml file add

<scriptfile>script.php</scriptfile>

add a file script.php to your install folder

<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
class com_mycomInstallerScript
{
    /**
     * Constructor
     *
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     */
     public function __construct(JAdapterInstance $parent)
     {
     }
    /**
     * Called on installation
     *
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     *
     * @return  boolean  True on success
     */
    public function install(JAdapterInstance $parent)
    {
    }

    /**
     * Called on uninstallation
     *
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     */
    public function uninstall(JAdapterInstance $parent)
    {

    }

    /**
     * Called on update
     *
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     *
     * @return  boolean  True on success
     */
    public function update(JAdapterInstance $parent)
    {
    }

    /**
     * Called before any type of action
     *
     * @param   string            $type    Which action is happening (install|uninstall|discover_install|update)
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     *
     * @return  boolean  True on success
     */
    public function preflight($type, JAdapterInstance $parent)
    {
    }

    /**
     * Called after any type of action
     *
     * @param   string            $type    Which action is happening (install|uninstall|discover_install|update)
     * @param   JAdapterInstance  $parent  The object responsible for running this script
     *
     * @return  boolean  True on success
     */
    public function postflight($type, JAdapterInstance $parent)
    {
        // get application
        $app = JFactory::getApplication();

        // set the default component settings
        if ($type === 'install')
        {
            // Install the global extenstion params.
            $db    = JFactory::getDbo();
            $query = $db->getQuery(true);
            // Field to update.
            $fields = array(
                $db->quoteName('params') . ' = ' . $db->quote('{"authorName":"Your Name","authorEmail":"Your email","your config.xml param":"your config.xml param value"}'),
            );
            // Condition.
            $conditions = array(
                $db->quoteName('element') . ' = ' . $db->quote('com_mycom')
            );
            $query->update($db->quoteName('#__extensions'))->set($fields)->where($conditions);
            $db->setQuery($query);
            $allDone = $db->execute();

        }
        // do any updates needed
        if ($type === 'update')
        {
        }

        return true;
    }

}
3
  • Thanks, but what would that line consist of exactly? Either 3.9 or 4. Both seem to behave the same.
    – mbrampton
    May 3 at 16:38
  • Thanks for developing that. I can see that it would work, but it has the drawback of requiring a JSON string that duplicates (in a different form) information that is in config.xml. The latter is still needed, as it provides structure for the parameters. With the same information in two places, maintenance is harder and there is a risk of inconsistency. So, although a possibility, it isn't an ideal solution, I'm afraid. The fact that it is in Component Builder seems to confirm that there is a real issue.
    – mbrampton
    May 5 at 14:31
  • I'd agree, it looks like as standard Joomla doesn't install the params and Llewellyn has coded this work around in JCB.
    – mfleeson
    May 5 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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