When the core locale module is enabled, trying to load a page with a CKEditor and the anchor_link plugin enabled result in a crash :

Exception: Only local files should be passed to _locale_parse_js_file() (line 1129 of core/modules/locale/locale.module)

Downgrading to 2.0.0-alpha2 solves the issue as a workaround.

How to reproduce :

- Install anchor_link and all related libraries
- Enable locale module
- Try to access a page with a CKEditor, results in a crash

It seems to be related with the "getLibraryUrl()" function of the AnchorLink class as it returns an absolute URL with http scheme and it is not allowed by _locale_parse_js_file().

It seems major to me as updating this module breaks any multilingual website.

Comments

lasensio created an issue. See original summary.

r81d3r’s picture

StatusFileSize
new709 bytes

I experienced the same issue on a system with enabled locale module under the current 2.2.0 version of anchor_link.

I could get the plugin to work by cutting

\Drupal::request()->getSchemeAndHttpHost()

out of

$originUrl = \Drupal::request()->getSchemeAndHttpHost() . \Drupal::request()->getBaseUrl();

to get a local path. I can now use the anchor_link plugin 2.2.0 with enabled locale module and recieved no errors so far.

You can test my changes by using the patch provided in my post.

edit: This can be only seen as a first approach cause it leads to following Warning after Cache clear in logs:

Warning: file_get_contents(/libraries/link/plugin.js): failed to open stream: No such file or directory in _locale_parse_js_file() (Zeile 1133 in [...]/core/modules/locale/locale.module)

r81d3r’s picture

StatusFileSize
new1003 bytes

The warning

Warning: file_get_contents(/libraries/link/plugin.js): failed to open stream: No such file or directory in _locale_parse_js_file() (Zeile 1133 in [...]/core/modules/locale/locale.module)

seems to be caused when $originUrl = \Drupal::request()->getBaseUrl(); results empty.

Adding an if statement

$originUrl = \Drupal::request()->getBaseUrl();

    $librarayPath = DRUPAL_ROOT . '/libraries/link';
    if(!empty($originUrl)){
      $librarayUrl = $originUrl . '/libraries/link';
    }
    else{
      $librarayUrl = $originUrl . 'libraries/link';
    }

seems to solve the problem by removing the first slash of the path if $originUrl results empty.

This can be tested with my _v2 patch.

mandus.cz’s picture

Assigned: Unassigned » mandus.cz

Your patch (v2) works. Thank you.

mandus.cz’s picture

Assigned: mandus.cz » Unassigned
rajab natshah’s picture

Thanks a lot, lasensio for reporting,
Thank you r81d3r for the patch!

Having the following in getLibraryUrl()

$originUrl = \Drupal::request()->getSchemeAndHttpHost() . \Drupal::request()->getBaseUrl();

There are two functions getLibraryUrl() and getLibraryPath()

Troubleshooting the issue

oleksandr yushchenko’s picture

Fixed to use getLibraryPath() instead of getLibraryUrl()

oleksandr yushchenko’s picture

Status: Active » Needs review
oleksandr yushchenko’s picture

One more with better implementation of getLibraryPath()

rajab natshah’s picture

Thanks Oleksandr for the patch

The full test for this change could be CKEditor settings + use in a text format

- Single language Drupal 8.8.2 + settings ( can you see the icons)
- Multi-language Drupal 8.8.2 + settings ( can you see the icons)
- Saving settings in default language.
- Saving settings in other languages.
- Editing in Default language.
- Editing in other languages.

For sure we should have an automated test. Be sure that all scenarios are working in the right way. ( in a new issue )

rajab natshah’s picture

Text formats and editors No Error when "Language", "Interface Translation", "Content Translation", "Configuration Translation" are disabled
Text formats and editors No Error when "Language" enabled

Text formats and editors Error When "Interface Translation" and "Language" enabled

[Mon Feb 24 11:59:09.617309 2020] [php7:notice] [pid 13462] [client ::1:56972] Uncaught PHP Exception Exception: "Only local files should be passed to _locale_parse_js_file()." at /var/www/html/dev/drupal80802t2/web/core/modules/locale/locale.module line 1129, referer: http://localhost/dev/drupal80802t2/web/admin/config/content/formats

https://api.drupal.org/api/drupal/core%21modules%21locale%21locale.modul...


// The file path might contain a query string, so make sure we only use the
  // actual file.
  $parsed_url = UrlHelper::parse($filepath);
  $filepath = $parsed_url['path'];

  // If there is still a protocol component in the path, reject that.
  if (strpos($filepath, ':')) {
    throw new Exception('Only local files should be passed to _locale_parse_js_file().');
  }
oleksandr yushchenko’s picture

When debugging, current approach with getLibraryUrl() generates absolute path to link plugin.js (https://test.com/libraries/link/plugin.js), while other libraries have relative path, also looking into 2.1 branch previously getLibraryPath() was used. So patch #9 will fix this issue and not impact icons as they using getLibraryUrl

rajab natshah’s picture

Title: Exception when locale module is enabled » Fix exception when locale module is enabled on Only local files should be passed to _locale_parse_js_file()

rajab natshah’s picture

Assigned: Unassigned » mohammed j. razem
Status: Needs work » Needs review

Committed ... Thank you :)

Using the new core logic and order untile Drupal 8.9.x and Drupal 9.x go out

  /**
   * Get the CKEditor Link library path.
   */
  protected function getLibraryPath() {
    // Following the logic in Drupal 8.9.x and Drupal 9.x
    // ----------------------------------------------------------------------
    // Issue #3096648: Add support for third party libraries in site specific
    // and install profile specific libraries folders
    // https://www.drupal.org/project/drupal/issues/3096648
    //
    // https://git.drupalcode.org/project/drupal/commit/1edf15f
    // -----------------------------------------------------------------------
    // Search sites/<domain>/*.
    $directories[] = \Drupal::service('site.path') . "/libraries/";

    // Always search the root 'libraries' directory.
    $directories[] = 'libraries/';

    // Installation profiles can place libraries into a 'libraries' directory.
    if ($this->installProfile) {
      $profile_path = drupal_get_path('profile', \Drupal::installProfile());
      $directories[] = "$profile_path/libraries/";
    }

    foreach ($directories as $dir) {
      if (file_exists(DRUPAL_ROOT . '/' . $dir . 'link/plugin.js')) {
        return $dir . 'link';
      }
    }

    return 'libraries/link';
  }
rajab natshah’s picture

Assigned: mohammed j. razem » Unassigned
rajab natshah’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.