No Code Attached Yet bug
avatar mbabker
mbabker
1 Dec 2018

It looks like this might have been exposed by #22090 as things were working OK in 3.8 and earlier, but that PR in and of itself isn't actually the problem here yet somehow applying it exposes the problem.

Extensions have to have a unique element name based on the extension type (and in the case of plugins, the folder; in the case of modules and templates I think this is also based on the client ID). So there are actually multiple records in that table where the element column is named "joomla" and this is perfectly acceptable.

If you have an extension script that extends Joomla\CMS\Installer\InstallerScript, its preflight method will try to validate that you aren't installing an older version if instructed to do so. To do that check, Joomla\CMS\Installer\InstallerScript::getItemArray() is called with a set of params that basically results in this query:

SELECT `manifest_cache` FROM `#__extensions` WHERE `element` = '$extension';

So going back to that example with extensions where the element column has the value of "joomla", this creates a non-unique result set. How did I run into this problem you ask? The joomla.org template is named "joomla" and trying to test installing an update I got a "Downgrading from version 13.1 to version 3.0.1-dev is not allowed." error message; except the template version isn't 13.1, that is the version of the Joomla library extension.

avatar mbabker mbabker - open - 1 Dec 2018
avatar joomla-cms-bot joomla-cms-bot - change - 1 Dec 2018
Labels Added: ?
avatar joomla-cms-bot joomla-cms-bot - labeled - 1 Dec 2018
avatar Fedik
Fedik - comment - 1 Dec 2018

it looks like getItemArray limited to single where clause by $identifier (that fine if select by ID),
possible solution is to allow $column and $identifier to be array, but this would be break of b/c, right?

avatar mbabker
mbabker - comment - 2 Dec 2018

possible solution is to allow $column and $identifier to be array, but this would be break of b/c, right?

For the most B/C behavior you'd have to introduce a new method because there are too many what ifs and we all know how people groan if you change anything (in theory since not typehinted you can change $column and $identifier to support both single scalar arguments and an array, but you'd need to type check the arguments and throw an Exception if the types don't match (both should be an array or both should be single scalar item (int, string, bool, etc.) or the number of array elements doesn't match; then there's the theoretical "adding new Exception is B/C break" but the method already doesn't catch exceptions from the database so adding a new RuntimeException in theory is OK since it matches what most would be catching if not handling the database specific exceptions only, which are newer than the installer script class in the first place; then there's the theoretical "but I've extended this method in a subclass" argument; then there's the even more painful "adding a new method to a class is a potential B/C break because I use this name in my subclass" argument).

avatar franz-wohlkoenig franz-wohlkoenig - change - 4 Mar 2019
Status New Discussion
avatar franz-wohlkoenig franz-wohlkoenig - change - 28 Mar 2019
Category com_installer
avatar franz-wohlkoenig franz-wohlkoenig - unlabeled - 4 Apr 2019
avatar franz-wohlkoenig franz-wohlkoenig - change - 4 Apr 2019
Labels Added: J3 Issue
avatar franz-wohlkoenig franz-wohlkoenig - labeled - 4 Apr 2019
avatar wilsonge
wilsonge - comment - 1 Jul 2019

I just came across this from elsewhere.

I originally based this on Nic's FOF installer script with a few common other things I'd seen around mixed in - so the original intent of this was just to be for components. Then I think that getItemArray i threw in from some module code I built a while ago. Just as some background for this. So definitely just an oversight and should be fixed in some way!

avatar mbabker mbabker - change - 19 Jul 2019
Status Discussion Closed
Closed_Date 0000-00-00 00:00:00 2019-07-19 15:52:50
Closed_By mbabker
avatar mbabker mbabker - close - 19 Jul 2019
avatar SharkyKZ
SharkyKZ - comment - 28 May 2020

Re-opening as this hasn't been solved. And the core preflight method is broken for the same reason.

avatar SharkyKZ SharkyKZ - change - 28 May 2020
Status Closed New
Closed_Date 2019-07-19 15:52:50
Closed_By mbabker
avatar SharkyKZ SharkyKZ - reopen - 28 May 2020
avatar SharkyKZ
SharkyKZ - comment - 28 May 2020

We need to make extension type, client ID and plugin folder available in the script. What would be the best way to do this?

  1. Add these properties to the script and have developers set them manually in their update scripts?
  2. Add these properties and getter methods in base InstallerAdapter?
  3. Add type getter to base adapter and the rest only to adapters that use them? Wrap in type and/or method_exists checks?
  4. Some other way?
avatar Hackwar
Hackwar - comment - 22 Nov 2022

This is the declaration of the method in question:

    /**
     * Builds a standard select query to produce better DRY code in this script.
     * This should produce a single unique cell which is json encoded - it will then
     * return an associated array with this data in.
     *
     * @param   string  $element     The element to get from the query
     * @param   string  $table       The table to search for the data in
     * @param   string  $column      The column of the database to search from
     * @param   mixed   $identifier  The integer id or the string
     *
     * @return  array  Associated array containing data from the cell
     *
     * @since   3.6
     */
    public function getItemArray($element, $table, $column, $identifier)

$identifier already can have multiple different values, so in order to be able to fix this in 4.x, why not extend the permissible values to an associative array? So when $identifier is an array and $column is null, we could then check for several columns. In Joomla\CMS\Installer\InstallerScript::preflight() we would have to then handle each extension type specifically. Yes, that is nasty, but it would allow us to fix this issue right now. What do you guys think? @HLeithner, @wilsonge, @zero-24 ?

avatar Hackwar
Hackwar - comment - 22 Nov 2022
avatar laoneo
laoneo - comment - 25 Nov 2022

But then I would rather create a new function which does it right and deprecate the faulty one.

avatar zero-24
zero-24 - comment - 25 Nov 2022

I do agree with @laoneo

avatar Hackwar Hackwar - change - 18 Feb 2023
Labels Added: No Code Attached Yet bug
Removed: ?
avatar Hackwar Hackwar - labeled - 18 Feb 2023
avatar chmst chmst - change - 13 Sep 2024
Labels Removed: J3 Issue
avatar chmst chmst - unlabeled - 13 Sep 2024

Add a Comment

Login with GitHub to post a comment