Greetings from the Acquia Hackathon! :) I'm floating around various teams and trying DMU on the modules they're trying to port to D8.

Here are the modules:

Let's find out what happens!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

webchick’s picture

Title: Attempt to upgrade CDN module to Drupal 8 and see what breaks » [meta] Attempt to upgrade several modules to Drupal 8 and see what breaks
Issue summary: View changes

Eh, let's make this a meta issue for all of them.

webchick’s picture

Issue summary: View changes
FileSize
37.25 KB
132.31 KB

First up, CDN. Here's the analyze report + generated patch.

Output:

$ drush dmu-upgrade cdn
Indexing...done.
Error at 497:44: expected ;                                          [error]
Error at 497:44: expected ;                                          [error]

Need to dig into that more and figure out what that's about.

webchick’s picture

Issue summary: View changes
FileSize
12.6 KB
71.93 KB

Now it's Purge's turn!

Output is clean:

$ drush dmu-upgrade purge
Indexing...done.
webchick’s picture

Issue summary: View changes
FileSize
50.39 KB
155.57 KB

Next up, the venerable Mollom module.

Lots of these:

$ drush dmu-upgrade mollom
Indexing...done.
Error at 2673:70: invalid expression                                 [error]
Error at 2673:70: invalid expression                                 [error]
Error at 2673:70: invalid expression                                 [error]
Error at 2673:70: invalid expression                                 [error]
Error at 2673:70: invalid expression                                 [error]
Error at 2673:70: invalid expression                                 [error]

Need to figure that out later.

webchick’s picture

Issue summary: View changes
FileSize
24.66 KB
33.99 KB

And last but not least, the fabulous Localization Client!

Moar errors:

$ drush dmu-upgrade l10n_client
Indexing...done.
Error at 497:33: expected ;                                          [error]
Error at 497:33: expected ;                                          [error]
Error at 497:33: expected ;                                          [error]
Error at 497:33: expected ;                                          [error]
Error at 497:33: expected ;                                          [error]

I'm going to start by digging into those errors, then try turning on the modules and see what blows up. ;)

webchick’s picture

As a first troubleshooting step, just tried composer update to get the latest version of All The Things™. However, this only brought down new copies of symfony/filesystem and symfony/finder; Pharborist was already pointing to dev-master. However, never hurts to have the latest version of stuff, so committed the update to composer.lock.

  • webchick committed 7b4d754 on 8.x-1.x
    Issue #2425401: Updating to latest version of All The Things™.
    
webchick’s picture

Created a pull request against Pharborist at https://github.com/grom358/pharborist/pull/198 so those error messages go from:

Error at 497:44: expected ;                                          [error]
Error at 497:44: expected ;                                          [error]

to:

Error at 497:44 in                                                   [error]
/Users/webchick/Sites/8.x/modules/cdn/cdn.basic.farfuture.inc:
expected ;
Error at 497:44 in                                                   [error]
/Users/webchick/Sites/8.x/modules/cdn/cdn.basic.farfuture.inc:
expected ;

...much easier. :)

webchick’s picture

So, CDN first. Relevant code is this in cdn.basic.farfuture.inc:

  $exists = file_exists($path);
  # Line 497...                            v character 44.
  \Drupal::logger('cdn')-> watchdog_notice : watchdog_critical('Nested HTTP request to generate %file: %result (URL: %url, time: !time).', array(
      '!time'   => (int) $_SERVER['REQUEST_TIME'],
      '%file'   => $path,
      '%url'    => $url,
      '%result' => $exists ? 'success' : 'failure',
    ));
  return $exists;

That does indeed seem to be a legit parse error.

The D7 code looks like this:

  $exists = file_exists($path);
  watchdog(
    'cdn',
    'Nested HTTP request to generate %file: %result (URL: %url, time: !time).',
    array(
      '!time'   => (int) $_SERVER['REQUEST_TIME'],
      '%file'   => $path,
      '%url'    => $url,
      '%result' => $exists ? 'success' : 'failure',
    ),
    $exists ? WATCHDOG_NOTICE : WATCHDOG_CRITICAL
  );
  return $exists;

So something's getting bungled when watchdog() is converted to Drupal::logger(). Filed an issue at #2425439: Conversion from watchdog() to \Drupal::logger() has problems when severity has logic for this one.

webchick’s picture

Next up, Mollom!

Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]
Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]
Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]
Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]
Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]
Error at 2673:70 in /Users/webchick/Sites/8.x/modules/mollom/mollom.module: invalid expression                                                                  [error]

(Incidentally, I am not sure why it feels compelled to tell me the same error multiple times, so filed #2425447: Pharborist errors reported multiple times about that.)

This one is confusing because...

/**
 * Log a Mollom system message.
 *
 * @param $log
 *   @todo A list of message parts. Each item is an associative array whose keys are
 *   log message strings and whose corresponding values are t()-style
 *   replacement token arguments. At least one part is required.
 *
# Line 2673...                                           position 70 v
 * In essence, this is a poor man's YAML implementation (give or take some
 * details, but note especially the indentation for array sub-elements).
 */

(I put some debugging code in that died right after the parse error happened to see if this was a situation where the real problem line just moved around, but that's indeed what it's choking on.)

Pharborist should basically be ignoring that entire line, because it's part of a comment. And even if it were somehow parsing that line, it's choking on a space, not any of the other special characters in that line. I tried deleting the space and re-adding it, in case there was some weird unicode character there or whatever, but git diff didn't show any changes.

Anyway, no clue. My best guess is something got flummoxed somewhere and caused it to feed the wrong line/position number into the exception, but for now spun off #2425475: Running DMU on Mollom causes Pharborist errors on a PHP comment line.

webchick’s picture

Ok, now let's play "What's up with l10n_client"?

Error at 497:33 in /Users/webchick/Sites/8.x/modules/l10n_client/l10n_client.module: expected ;                                                                 [error]
Error at 497:33 in /Users/webchick/Sites/8.x/modules/l10n_client/l10n_client.module: expected ;                                                                 [error]
Error at 497:33 in /Users/webchick/Sites/8.x/modules/l10n_client/l10n_client.module: expected ;                                                                 [error]
Error at 497:33 in /Users/webchick/Sites/8.x/modules/l10n_client/l10n_client.module: expected ;                                                                 [error]
Error at 497:33 in /Users/webchick/Sites/8.x/modules/l10n_client/l10n_client.module: expected ;                                                                 [error]
function l10n_client_save_string() {
  # Line 497       character 33 v
  $user = \Drupal::currentUser(), $language;

Um, yep, that'd do it. :)

Original code was:

function l10n_client_save_string() {
  global $user, $language;

Need to make replacement of global $user smarter. Filed #2425483: Fix parse errors caused by multiple global variable declarations on the same line. for that.

webchick’s picture

webchick’s picture

And new patch for CDN with #2425439: Conversion from watchdog() to \Drupal::logger() has problems when severity has logic now fixed.

Still do not get what's up with Mollom, so I'll skip that one for now.

Next step is to actually try installing all of these and see what burns. ;)

webchick’s picture

Purge... Enables cleanly!

CDN:

 Fatal error: Declaration of Drupal\cdn\Form\CdnAdminGeneralSettingsForm::buildForm() must be compatible with Drupal\Core\Form\FormInterface::buildForm(array $form, Drupal\Core\Form\FormStateInterface $form_state) in /Users/webchick/Sites/8.x/modules/cdn/src/Form/CdnAdminGeneralSettingsForm.php on line 14

That looks like a good one to fix.

And since that just broke my local, will test Mollom and Localization Client in a few. ;)

webchick’s picture

webchick’s picture

Ok, that one's gone (thanks, phenaproxima!) Now CDN fails on enable with:

 Fatal error: Can't use method return value in write context in /Users/webchick/Sites/8.x/modules/cdn/src/Form/CdnAdminOtherSettingsForm.php on line 282

Line 282 is the closing } of the class definition. WAT? I tried Googling the error but get a bunch of references to functions like empty() and isset() and unset(), none of which are in that file anywhere. Here's a copy of the file, which looks fine to me at first glance.

For now I'm going to chalk it up to something in CDN being goofy (since a DMU upgrade of Diff worked just fine) and move onto something else.

webchick’s picture

Mollom goes boom during installation on:

 Fatal error: Cannot use isset() on the result of a function call (you can use "null !== func()" instead) in /Users/webchick/Sites/8.x/modules/mollom/src/Form/MollomAdminConfigureForm.php on line 26

Line 26 is:

# This one here.
      if (!isset($form_state->getStorage())) {
        $form_state->setStorage('select');
      }

Hm, interesting. I actually wonder if the CDN failure is related now, since that sounds awfully similar to what was said in http://stackoverflow.com/questions/1075534/cant-use-method-return-value-....

In Drupal 7, this used to be:

    if (!isset($form_state['storage']['mollom_form'])) {
      $form_state['storage']['step'] = 'select';
    }

...which was not a problem because isset() was checking a variable, not the result of a function. Spun off #2426635: When $form_state is converted, various code that checks a form state variable fails about this.

Berdir’s picture

This seems as good as any other place to write down a few notes, I've been testing this with https://www.drupal.org/project/new_relic_rpm, which has a few settings and is otherwise a very "low level module".

* A query like db_query("UPDATE {system} SET weight = -20 WHERE name = 'new_relic_rpm'") in hook_install() can't be converted as a database query, as there is no system table anymore. module_set_weight() can be used instead. Doesn't need to be a full conversion, but detecting and suggesting it in a comment would be great, as it is not obvious to find.

* I noticed the report says that variable uninstallation is no longer necessary, but the code is still there and was converted. Maybe add an inline comment too?

* links.task.yml is missing the base_route where the local task should be displayed. Again, maybe just add a comment, that has the old path or something?

* Nested menu links in the same module could automatically set the parent, e.g. admin/reports/something and admin/reports/something/detail-page.

* @file docblock for new classes is missing a newline:

<?php /**
 * @file
 * Contains \Drupal\new_relic_rpm\EventSubscriber\BootSubscriber.
 */
?>

* variables were always prefixed with the module name. That is no longer needed for config settings. So some_module_my_var should become my_var in some_module.settings.

* watchdog_severity_levels() is now Drupal\Core\Logger\RfcLogLevel::getLevels()

* public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface &$form_state) => & needs to be removed.

* buildForm() should be before submitForm()

* _theme() is now \Drupal::theme()->render()

To be continued...

webchick’s picture

AWESOME! Please keep feedback like this coming!

Berdir’s picture

* services should be prefixed with the module name, so my_module.something instead of jus "something".

* I noticed a lot of code is still left in the .module file, like hook_permission()/hook_menu(), init/boot hooks and so on. Adding a comment there and saying that it is dead code, and should be deleted after checking the conversion would be cool.

Really nice work so far. I've pushed a first 8.x-1.x branch for my module, and this saved me a lot of tedious, boring work, allowing me to focus on the more interesting parts of the port. #2461493: Drupal 8 port

Berdir’s picture

So, had a look at a bigger and fairly complex project: userpoints 7.x-2.x

More random feedback, in no specific order.

$ drush dmu-upgrade userpoints
Indexing...done.
Cannot get ahold of the controller class for userpoints_transaction_type entity type.                                                                                         
userpoints_get_points_list() cannot be parametrically rewritten because account is reassigned.

* For the controller class, if it doesn't exist, just ignore it and create the entity type anyway. Maybe add a comment somewhere. In my case, it was EntityAPIControllerExportable, which essentially means that it should be a config entity now.
* I also had to update some String:: calls to Safemarkup, as format() moved there (in the drupalmoduleupgrader code, when those exceptions above are thrown)
* decode_entities in the function list is now \Drupal\Component\Utility\Html::decodeEntities (No longer String::)
* Minor: entity is no longer a module dependency and could be ignored
* It chokes on variable_get()/variable_set() when constants are used. Might not be too hard to support them but I'm not sure what to do. I'd recommend to just drop them and convert to the literal value.
* check_plain is apparently missing in the function replacement list, also filter_xss and filter_xss_admin.
* Most of hook_help() could be updated easily. Different arguments, route names instead of paths in the switch statement. (just update the arguments and document it if you can't handle those yet)
* It would be nice if it could handle the static parts of hook_menu(), even if parts are dynamic.
* dynamic permissions should be put into a permission callback, see node.permissions.yml
* the file/function pattern in hook_theme() is inverted. in 7.x, you have to specify if it is a file, now you have to specify if it is a function. So if it does not have a file, you could add 'function' => same_as_key. That said, it is recommended to convert it to a twig file now. So you might want to just add a comment about that.
* token_find_with_prefix() => \Drupal::token()->findWithPrefix()
* token_generate() -> \Drupal::token()->generate()
* hook_field_extra_fields() has been renamed to hook_entity_extra_field_info(), implementation is basically the same.
* hook_views_api can be dropped.
* Somehow it only converted the first of multiple classes in my .test file.
* entity_uri('userpoints_transaction', $child_transaction) is now basically $child_transaction->url(), although it depends a bit on the case (could also be urlInfo() or link())

pingwin4eg’s picture