No Code Attached Yet
avatar matteo-galletti
matteo-galletti
10 Jan 2022

Is your feature request related to a problem? Please describe.

The capabilities listed by com_privacy component can be extended only through a plugin that belongs to one of the pre-selected groups. What if I need to mention the cookies used by a component without the usage of a plugin?

Describe the solution you'd like

I would like to propose a new technique to allow the extendibility of the capabilities list simply by relying on the helper file (and related class) that a component or a module might have already declared to support the prepareUpdate method, invoked by UpdateModel::preparePreUpdate().

In case of a component, the resulting file should be already built as follows:

class FooHelper
{
    /**
     * Method to add parameters to the update extra query.
     *
     * @param   Update  &$update  An update definition
     * @param   JTable  &$table   The update instance from the database
     *
     * @return  void
     *
     * @since   3.7.0
     */
    public static function prepareUpdate(&$update, &$table)
    {
        $update->set('extra_query', 'ordnum=ABC123');
    }
}

My request aims to introduce a new static method to allow the components and the modules to return a list of points to be displayed within the Privacy: Extension Capabilities page. So, if we take a component named com_foo as example, the class previously described should become:

class FooHelper
{
    /**
     * Method to add parameters to the update extra query.
     *
     * @param   Update  &$update  An update definition
     * @param   JTable  &$table   The update instance from the database
     *
     * @return  void
     *
     * @since   3.7.0
     */
    public static function prepareUpdate(&$update, &$table)
    {
        $update->set('extra_query', 'ordnum=ABC123');
    }

    /**
     * Retrieve the extension capabilities.
     *
     * @return  array
     *
     * @since   3.9.0
     */
    public static function getCapabilities()
    {
        return [
            'The component uses the cookie for reason A',
            'The component stores the IP address for reason B',
        ];
    }
}

At this point the CapabilitiesModel::getCapabilities() method should load the list of all the installed components and modules and scan them one by one to look for the helper file:

  • /administrator/components/com_foo/helpers/foo.php (in case of a component)
  • /modules/mod_foo/helper.php (in case of a module)

My entire request is based on a piece of code already used by the getCapabilities() method. Here it is:

// We are going to "cheat" here and include this component's capabilities without using a plugin
$extensionCapabilities = [
    Text::_('COM_PRIVACY') => [
        Text::_('COM_PRIVACY_EXTENSION_CAPABILITY_PERSONAL_INFO'),
    ],
];

Why com_privacy should be able to "cheat" and com_foo not?

Additional context

All the administrator modules should be completely ignored, since their effect cannot interfere with the front-end user experience.

Should the system ignore the extensions that have been disabled? In case the answer is yes, then the system should fetch a list of installed components and site modules from the #__extensions database table. Alternatively it would be enough a direct foreach to the targeted folders. Something like:

$lang = Factory::getLanguage();

// scan components
foreach (Folder::folders(JPATH_ADMINISTRATOR . '/components') as $component)
{
    $ename = str_replace('com_', '', $component);
    $fname = $ename . '.php';
    $cname = ucfirst($ename) . 'Helper';

    $path = JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $fname;

    if (File::exists($path))
    {
        require_once $path;

        if (class_exists($cname) && is_callable(array($cname, 'getCapabilities')))
        {
            // autoload language SYS file for a correct translation
            $lang->load($component . '.sys');

            $section = Text::_(strtoupper($component));

            $extensionCapabilities[$section] = call_user_func(array($cname, 'getCapabilities'));
        }
    }
}

// scan site modules
foreach (Folder::folders(JPATH_SITE . '/modules') as $module)
{
    $cname = str_replace('_', '', $module) . 'Helper';
    $path = JPATH_SITE . '/modules/' . $module . '/helper.php';

    if (File::exists($path))
    {
        require_once $path;

        if (class_exists($cname) && is_callable(array($cname, 'getCapabilities')))
        {
            // autoload default language file for a correct translation
            $lang->load($module);

            $section = Text::_(strtoupper($module));

            $extensionCapabilities[$section] = call_user_func(array($cname, 'getCapabilities'));
        }
    }
}
avatar matteo-galletti matteo-galletti - open - 10 Jan 2022
avatar joomla-cms-bot joomla-cms-bot - change - 10 Jan 2022
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 10 Jan 2022
avatar drmenzelit
drmenzelit - comment - 18 Jan 2022

Moving this to discussions

Add a Comment

Login with GitHub to post a comment