17

I am the author of the Date iCal module, and the new major version I'm working on (3.x) requires a two-part schema update for users who had 2.x installed. I've written the update hook that makes these changes, but if one of my users fails to run the database update script, they will get an error message relating to their iCal feeds importers.

The right solution is for them to run the update script... but if they just go in and manually change their importers to get rid of the message, their importers will remain permanently broken (because the second part of the schema update won't have been executed).

So is there any way to display a message to users who haven't run the update? Or somehow forcibly execute the update hook the first time a page load occurs when 3.x gets installed overtop of 2.x?

  • 2
    I would imagine you could do a variable_set() in your update function that sets a variable when it was successfully run that you could look at inside a _preprocess_page() but you'd be looking at it every time so not sure how performance friendly this would be. – Jimajamma Nov 12 '13 at 20:07
4

extending on comment from Jimajamma:

do a variable_set() in your update function that sets a variable when it was successfully run that you could look at inside a _preprocess_page()

and instead of checking this on every page load do it only if browsing the admin area and if the installed version is 3.0 (3.1, 3.2, kill that check if you stop supporting the old version as an upgrade path).

Additionally make use of hook_requirements to provide feedback on the status report page:

Check installation requirements and do status reporting.
(...)
The 'runtime' phase is not limited to pure installation requirements but can also be used for more general status information like maintenance tasks and security issues.

14

There are few ways of forcing module update.

  1. Calling the update function directly.

    $sandbox = [];
    module_load_include('install', 'FOO');
    FOO_update_7001($sandbox);
    
  2. Resetting the schema version to the point of interest and run the updates again as usual.

    drupal_set_installed_schema_version('module_name', '7000');
    

    Or reset to re-run only the latest update schema:

    drupal_set_installed_schema_version('foo', drupal_get_installed_schema_version('foo') - 1);
    

    Notes:

    • This can be placed in hook_install, so during the update process all sequent update hooks would be executed.
    • In order to use this function outside of the installation file, you've to include Drupal install.inc first and installation file of the module, e.g.

      require_once DRUPAL_ROOT . '/includes/install.inc';
      module_load_include('install', 'foo');
      
    • Consider adding ini_set('max_execution_time', 0); for longer installation updates to prevent PHP timeouts.
  3. Using drush. Find below few examples:

    • drush eval 'module_load_include('install', 'foo'); $s = []; foo_update_7001($s);'
    • drush sqlq "UPDATE system SET schema_version = 7000 WHERE name = 'foo'" && drush -y updb
  • 1
    Oh nice, I didn't know about drupal_set_installed_schema_version(). That'd be super handy for debugging update hooks! – coredumperror Jul 22 '15 at 18:18
  • 1
    So the main problem with putting it into hook_install() is running long batched (sandboxed) updates. In ideal situation, there should be a way to trigger updates in the same way as update.php does with restarting PHP thread to prevent timeouts. Ant ideas how to do that? – Alex Skrypnyk Feb 1 '17 at 9:22
  • @Alex.Designworks You can add ini_set('max_execution_time', 0); before triggering the updates. – kenorb Feb 1 '17 at 10:13
1

(Reworded into an answer)

You could "SELECT schema_version FROM system" to detect whether an update has been performed. If not, then refuse to run (with an error message).

  • Please reword your answer, and try to give a usage example. – Елин Й. Nov 20 '13 at 20:28
  • Ignore this comment. – coredumperror Nov 21 '13 at 2:00
  • I'm afraid that won't work, because the functionality in question is a plugin for another module, and I can't prevent that module from letting users mess with their importers. – coredumperror Nov 21 '13 at 2:04
  • You cannot check the schema version of the module which you intend to monitor for updates? – user18099 Nov 27 '13 at 16:08
0

I agree with the above suggestions - my only addition would be to investigate "Triggers and Actions" also - it seems that you need an action (notify user or run update) to occur when a trigger (user checks admin page, etc) is pulled. For use examples see the Examples module, there are both action and trigger example code. :)

0

function MYMODULE_install() { $functions = get_defined_functions(); foreach ($functions['user'] as $function) { if (strpos($function, 'MYMODULE_update_') === 0) { call_user_func($function); } } }

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.