Problem/Motivation

In core/includes/common.inc there are 2 functions: archiver_get_extensions() and archiver_get_archiver() that, conceptually, could be moved to archiver plugin manager: \Drupal\Core\Archiver\ArchiverManager (plugin.manager.archiver).

Proposed resolution

Add archiver_get_extensions() and archiver_get_archiver() to \Drupal\Core\Archiver\ArchiverManager and deprecate the procedural versions.

Remaining tasks

None.

User interface changes

None.

API changes

New methods in \Drupal\Core\Archiver\ArchiverManager:

  • ::getExtensions()
  • ::getArchiverByFile()

Data model changes

None.

Comments

claudiu.cristea created an issue. See original summary.

claudiu.cristea’s picture

Status: Active » Needs review
StatusFileSize
new10.22 KB
claudiu.cristea’s picture

Issue summary: View changes
StatusFileSize
new2.22 KB
new11.14 KB

Renamed ::getArchiver() to a more meaningful ::getArchiverByFile(). Replaced a reference to the deprecated function.

claudiu.cristea’s picture

Issue summary: View changes
claudiu.cristea’s picture

Issue tags: +@deprecated

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

claudiu.cristea’s picture

Issue tags: +Kill includes
claudiu.cristea’s picture

StatusFileSize
new2.93 KB
new11.75 KB

Rerolled. Fixed version, added deprecated error triggers, CR and others.

fenstrat’s picture

Status: Needs review » Reviewed & tested by the community

This looks good, as does the CR. Manually verified all instances of archiver_get_extensions() and archiver_get_archiver are gone.

The last submitted patch, 3: 2908176-3.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Archiver/ArchiverManager.php
@@ -61,4 +72,50 @@ public function getInstance(array $options) {
+   *   If no archiever plugin qualifies for the given file.

Misspelt.

+++ b/core/includes/common.inc
@@ -1227,43 +1227,43 @@ function drupal_check_incompatibility($v, $current_version) {
 function archiver_get_archiver($file) {
-  // Archivers can only work on local paths
-  $filepath = \Drupal::service('file_system')->realpath($file);
-  if (!is_file($filepath)) {
-    throw new Exception(t('Archivers can only operate on local files: %file not supported', ['%file' => $file]));
-  }
-  return \Drupal::service('plugin.manager.archiver')->getInstance(['filepath' => $filepath]);
+  @trigger_error("archiver_get_archiver() is deprecated in Drupal 8.7.x and will be removed in Drupal 9.0.x. Use \Drupal::service('plugin.manager.archiver')->getExtensions() instead. See https://www.drupal.org/node/2999951.");
+  return \Drupal::service('plugin.manager.archiver')->getArchiverByFile($file);
 }

I'm not sure that this is worth having in the API. We replace this with \Drupal::service('plugin.manager.archiver')->getInstance(['filepath' => $filepath]) and make it the caller's responsibility to have a real path. Since looking at update_manager_file_get() which provides the path for the only real usage in core I think this will return paths that will work with \Drupal::service('plugin.manager.archiver')->getInstance(['filepath' => $filepath])

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.78 KB
new10.68 KB

There's 8 usages in contrib http://grep.xnddx.ru/search?text=archiver_get_archiver and all of it targeted for local file.
2 of them using to make "realpath" conversion before calling the function.
I think it needs to change docs of getInstance() to point that filepath is required key in configuration to instantiate plugin (probably needs follow-up)

Re-rolled and and trying to implement #12

As getInstance() supposed to work on local files only I'm sure it just needs to be documented somehow

andypost’s picture

Also it needs deprecation test and update change record

berdir’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Archiver/ArchiverManager.php
@@ -26,11 +34,14 @@ class ArchiverManager extends DefaultPluginManager {
    */
-  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, FileSystemInterface $file_system) {
     parent::__construct('Plugin/Archiver', $namespaces, $module_handler, 'Drupal\Core\Archiver\ArchiverInterface', 'Drupal\Core\Archiver\Annotation\Archiver');
     $this->alterInfo('archiver_info');
     $this->setCacheBackend($cache_backend, 'archiver_info_plugins');
+    $this->fileSystem = $file_system;

+++ b/core/modules/update/src/Form/UpdateManagerInstall.php
@@ -47,11 +55,14 @@ class UpdateManagerInstall extends FormBase {
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, $site_path) {
+  public function __construct($root, ModuleHandlerInterface $module_handler, $site_path, ArchiverManager $archiver_manager) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->sitePath = $site_path;
+    $this->archiverManager = $archiver_manager;
   }

These need to do the "NULL dance". optional argument, if (!$file_system), then fetch from \Drupal::service() and do a @trigger_error().

vacho’s picture

StatusFileSize
new10.88 KB

Solved "NULL dance" for ArchiverManager::construct()

vacho’s picture

StatusFileSize
new1.19 KB

Upload interdiff

vacho’s picture

Status: Needs work » Needs review
alexpott’s picture

+++ b/core/lib/Drupal/Core/Archiver/ArchiverManager.php
@@ -16,6 +17,13 @@
+  /**
+   * The file system service.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  protected $fileSystem;

Is this needed? I can't see where it is used.

YurkinPark’s picture

StatusFileSize
new8.64 KB
new2.34 KB

Note fixed

andypost’s picture

StatusFileSize
new4.03 KB
new10.05 KB

Add test and clean-up messages

andypost’s picture

StatusFileSize
new1.01 KB
new10.05 KB

valid path

The last submitted patch, 21: 2908176-21.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 22: 2908176-22.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.18 KB
new10.05 KB

Fix codestyle & uncomment test

Still can't figure why tests fails

There were 2 failures:

1) Drupal\KernelTests\Core\Common\LegacyFunctionsTest::testArchiverGetExtensions
Failed asserting that string matches format description.
--- Expected
+++ Actual
@@ @@
 @expectedDeprecation:
-%A  archiver_get_extensions() is deprecated in Drupal 8.7.0 and will be removed in Drupal 9.0.0. Use \Drupal\Core\Archiver\ArchiverManager::getExtensions() instead. See https://www.drupal.org/node/2999951
+  Install profile will be a mandatory parameter in Drupal 9.0.

2) Drupal\KernelTests\Core\Common\LegacyFunctionsTest::testArchiverGetArchiver
Failed asserting that string matches format description.
--- Expected
+++ Actual
@@ @@
 @expectedDeprecation:
-%A  archiver_get_archiver() is deprecated in Drupal 8.7.0 and will be removed in Drupal 9.0.x. Instead, get plugin.manager.archiver service from container and call getInstance() method on it. For example $archiver->getInstance(["filepath" => $file]); See https://www.drupal.org/node/2999951
+  Install profile will be a mandatory parameter in Drupal 9.0.
andypost’s picture

StatusFileSize
new2.77 KB
new10.09 KB

sadly missed that

The last submitted patch, 25: 2908176-25.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 26: 2908176-26.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review

still applies

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mile23’s picture

Status: Needs review » Needs work
+++ b/core/includes/common.inc
@@ -1245,37 +1245,43 @@ function drupal_check_incompatibility($v, $current_version) {
+ * @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use
...
+ * @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Instead,

8.8.x now.

Otherwise LGTM.

naveenvalecha’s picture

Status: Needs work » Needs review
StatusFileSize
new10.09 KB
new4.31 KB

Addressed #31

+++ b/core/modules/update/src/Form/UpdateManagerInstall.php
@@ -47,11 +55,14 @@ class UpdateManagerInstall extends FormBase {
+  public function __construct($root, ModuleHandlerInterface $module_handler, $site_path, ArchiverManager $archiver_manager) {

We're doing the change in the constructor in a form. However, forms are internal but in the recent issues I have worked on we preserve the BC so that the contrib that extends it doesn't break. So I looked at its usage http://grep.xnddx.ru/search?text=UpdateManagerInstall&filename= and it's not used in contrib apart from portfolio_theme module which committed the drupal core in the repo. Also, there are few other modules which are altering the module so we're good with respect to this change.

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community

Since we have the create() pattern here, I think it's fine to not do a trigger_error for the additional parameter.

larowlan’s picture

review credits

  • larowlan committed fc301d8 on 8.8.x
    Issue #2908176 by andypost, claudiu.cristea, vacho, YurkinPark,...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed fc301d8 and pushed to 8.8.x. Thanks!

published change record

Status: Fixed » Closed (fixed)

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

dww’s picture

Note: y'all broke the Update Manager's ability to install from .zip files with this change.

#3101299: Install module from .zip URL fails

// Archivers can only work on local paths
This comment in archiver_get_archiver() was trying to say that \ZipArchive::open() can't handle file streams at all. We absolutely need the call to realpath(), which is now gone.

I don't understand why the new service doesn't do this for you automatically, and we force the callers to have to worry about this.

But if we're forcing callers to worry about it, we failed to properly do this in update_manager_file_get(). It's still returning paths like:

temporary://update-cache-edd502a3/pathauto-8.x-1.6.zip

I'll be the first to admit that update.module's tests are sorely lacking in all sorts of ways.

Obviously, way too late to revert this now, so I guess we'll just fix it at #3101299 and backport the fix.

I'd greatly appreciate it if any of you who were involved here would be willing to help out over there, especially with input on where/how to add tests for this so we don't break it again.

Thanks!
-Derek

dww’s picture

p.s. For now, I edited the CR to match what the final patch here did, and to include the warning about callers needing to use realpath():

https://www.drupal.org/node/2999951/revisions/view/11422137/11767365