Hello,
I am wondering if there's any collective will to
Add:
module_installed($module)
Alongside:
module_exists($module)
In:
core/includes/modules.inc
Here's the source for module_exists($module)
/**
* Determines whether a given module exists.
*
* @param string $module
* The name of the module (without the .module extension).
*
* @return bool
* TRUE if the module is both installed and enabled, FALSE otherwise.
*/
function module_exists($module) {
$list = module_list();
return isset($list[$module]);
}
Here's what I whipped up for module_installed($module)
/**
*
* @name
* module_installed()
*
* @description
* Determines if a module is installed or not.
*
* @param string $module
* The name of the module (without the .module extension).
*
* @return bool
* TRUE if the module is installed, FALSE otherwise.
*/
function module_installed($module) {
$result = db_query("SELECT * FROM {system} WHERE type = 'module' AND name = '" . $module . "'");
return $result->rowcount() ? TRUE : FALSE;
}
EDIT: See discussion of db_query #Placeholders at:
https://www.drupal.org/docs/7/api/database-api/static-queries
The above query should be formatted differently to conform to Drupal best practices....
$result = db_query("SELECT * FROM {system} WHERE type = 'module' AND name = :module", array(':module'=> $module);
Comments
The system table shows rows of modules that are or were present in the codebase. So it would be unreliable.
Perhaps if I understood what you're trying to accomplish. Are you saying "installed" as in the module code is present, or that the module is enabled? If the latter then module_exists() already does that. As for the former, I don't think there's a performant way to do that.
In addition to what Herb said, it's important to clarify the terminology used by Backdrop.
The list of modules displayed in
/admin/modules
is the result of reading the.info
files placed within the usual module locations (modules
folder,core/modules
folder andsites/XXX/modules
folder), and lists any module that containstype = module
in those .info files. This list is stored in thesystem
table. When you remove a module folder from themodules
folder, thesystem
table will not be updated (and the module record will not be removed) until you either clear caches, or visit theadmin/module
page. Therefore, your code (IF what you are trying to do is to see if the module code is in themodules
folder) will be unreliable.In addition, your syntax for
db_query
is not great. You don't want to concatenate strings for the query. Instead you should use placeholders.Hello @herb and @argiepiano,
First of all, many thanks for taking the time to supply your helpful comments.
I was also puzzled by lingering module-related artifacts I found in the system.
I too noticed that the BCMS system state was "unreliable" with respect to reporting what I would normally consider to be the "true" status of a module, which could potentially be expressed via the following states:
Perhaps I've missed a state. If so, please add it.
In any case, it looks to me like the system has module management issues in terms of nomenclature and functionality. My experience was that when I used the "Uninstall" feature to manipulate the status of a module, its code remained resident on the disk and some of its data remained resident in the system table.
This system behavior might reasonably be considered counter-intuitive or even "wrong" by the uninitiated, who (based on the behavior exhibited by other systems) might expect an "uninstall" process to be the equivalent of something being purged from a system. It might even be considered by some as being immoral.
In previous eras, when disk space was more precious, people complained quite loudly if you couldn't purge a software and all of its cyber-leavings from a system via its "uninstall" process. It was seen as a major flaw. It forced OS vendors to publish strict guidelines and processes regarding how 3rd party software could be installed (and potentially uninstalled), mostly due to incredibly negative customer pressure. It was the impetus for the creation of specialized, system-level install/uninstall software like Microsoft Windows Installer and Composer (and many, many other such-like "package managers").
Anyways, to illustrate why I am even looking at this situation, here's a potential use case that may help to clarify what I am thinking about:
On disk, the files are laid out like this:
Drupal
└── ubercart
└── payment
├── uc_2checkout
├── uc_authorizenet
├── uc_credit
├── uc_cybersource
├── uc_google_checkout
├── uc_payment
├── uc_payment_pack
└── uc_paypal
With the above architecture, wouldn't it be nice to have the "payment" module be able to: (1) Tell the Administrator what the Ubercart Payment sub-system is all about; then (2) Inform the Administrator about the universe of payment method options available to them by displaying something like this?
--------------------------------------------------------------------
Ubercart Payment Methods
Ubercart Payment Methods expose various methodologies by which customers might pay for things. The Ubercart Payment Methods (uc_payment) module ships with several "core" Payment Methods pre-installed (including the highly popular "PayPal Payment Method), and there are a number of 3rd party "contributed" Payment Methods available for download.
Payment Methods:
PayPal is enabled (disable | uninstall | quarantine)
Authorize.net is ready but disabled (enable | uninstall | quarantine)
Google Checkout is quarantined (ready | uninstall)
HSBC PayMe is installed but unready (ready | uninstall | quarantine)
AliPay is uninstalled (quarantine | delete)
X is possible (download)
Y is possible (download)
Z is possible (download)
--------------------------------------------------------------------
I may not have the above right. I did not develop a state diagram, but what I want to do is explore the feasibility of doing something along the above lines without horribly breaking BCMS.
Finally, @argiepiano, thanks for the tips regarding coding approach, I will look up the approach you indicated, though I wonder why the method you outlined is preferred? A few words on that topic would be much appreciated - I very much feel like "I don't know what I don't know" :)
EDIT: Likely he meant "parameters" and the two main reasons for taking this approach are (A) Avoiding SQL injection and other nasty behaviors that result from pasting unsanitized user input directly into SQL statements ($module in this case is a programmer-derived value rather than a user-supplied value, but the point is taken. [the original approach taken in module.inc with respect to enabled modules is less direct; it chains together two functions that (1) generate a list of all modules; and (2) searches for a match in that list for the parameter given, which in its own way would likely avoid SQL injection, as the argument/parameter is never implicated in a SQL statement, but rather a comparison]); and (B) Improved performance as parameterized queries can quite easily become stored procedures. In short, there are both sanitization and speed advantages.
EDIT: https://www.php.net/manual/en/mysqli-stmt.bind-param.php
@all - Does the BCMS Project have its own Official Programming Style Guide, or has it adopted the Style Guide of another project? I'd like to understand this subject better so I don't have to revise my work as much, moving forward.
EDIT: https://backdropcms.org/project/styleguide
EDIT: https://docs.backdropcms.org/php-standards
EDIT: https://docs.backdropcms.org/css-standards
EDIT: https://github.com/backdrop-ops/styleguide
Thanks!
g.
----
Update,
I saw this in the modules management area when I created a brand-new TEST module:
The following shows up in the system table:
(schema)
> show columns from system;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| filename | varchar(255) | NO | PRI | | |
| name | varchar(255) | NO | | | |
| type | varchar(12) | NO | MUL | | |
| owner | varchar(255) | NO | | | |
| status | int(11) | NO | MUL | 0 | |
| bootstrap | int(11) | NO | | 0 | |
| schema_version | smallint(6) | NO | | -1 | |
| weight | int(11) | NO | | 0 | |
| info | blob | YES | | NULL | |
+----------------+--------------+------+-----+---------+-------+
(data)
> select filename, name, type, status from system where name = 'TEST';
+--------------------------------------------+------+--------+--------+
| filename | name | type | status |
+--------------------------------------------+------+--------+--------+
| sites/all/modules/_custom/test/test.module | test | module | 0 |
+--------------------------------------------+------+--------+--------+
So it looks to me like there's enough clues in the system table to determine at least some of the states I think are possible and want:
Opinions?