From 0f7d46f9ffed77eef8e782bdb87d48857e6ba07d Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Sat, 16 Dec 2023 16:58:44 +0000 Subject: [PATCH] Issue #3397575 by kim.pepper, sourabhjain, alexpott, longwave: Deprecate file_progress_implementation() and replace with extension_loaded('uploadprogress') --- core/modules/file/file.install | 76 ++++++++---------- core/modules/file/file.module | 6 ++ .../Controller/FileWidgetAjaxController.php | 3 +- core/modules/file/src/Element/ManagedFile.php | 20 +++-- .../Plugin/Field/FieldWidget/FileWidget.php | 2 +- .../tests/src/Kernel/LegacyFileModuleTest.php | 30 +++++++ .../tests/src/Kernel/RequirementsTest.php | 80 +++++++++++++++++++ core/phpstan-baseline.neon | 5 -- 8 files changed, 160 insertions(+), 62 deletions(-) create mode 100644 core/modules/file/tests/src/Kernel/LegacyFileModuleTest.php create mode 100644 core/modules/file/tests/src/Kernel/RequirementsTest.php diff --git a/core/modules/file/file.install b/core/modules/file/file.install index de86c7bca84b..7745a54041fc 100644 --- a/core/modules/file/file.install +++ b/core/modules/file/file.install @@ -65,53 +65,43 @@ function file_schema() { function file_requirements($phase) { $requirements = []; - // Check the server's ability to indicate upload progress. - if ($phase == 'runtime') { - $description = NULL; - $implementation = file_progress_implementation(); - // The environment variable might be missing. Fallback to an empty string to - // prevent passing NULL to preg_match(), a few lines later. - $server_software = \Drupal::request()->server->get('SERVER_SOFTWARE', ''); + if ($phase != 'runtime') { + return $requirements; + } + + $server_software = \Drupal::request()->server->get('SERVER_SOFTWARE', ''); - // Test the web server identity. - if (preg_match("/Nginx/i", $server_software)) { - $is_nginx = TRUE; - $is_apache = FALSE; - $fastcgi = FALSE; - } - elseif (preg_match("/Apache/i", $server_software)) { - $is_nginx = FALSE; - $is_apache = TRUE; - $fastcgi = str_contains($server_software, 'mod_fastcgi') || str_contains($server_software, 'mod_fcgi'); - } - else { - $is_nginx = FALSE; - $is_apache = FALSE; - $fastcgi = FALSE; - } + // Get the web server identity. + $is_nginx = preg_match("/Nginx/i", $server_software); + $is_apache = preg_match("/Apache/i", $server_software); + $fastcgi = $is_apache && ((str_contains($server_software, 'mod_fastcgi') || str_contains($server_software, 'mod_fcgi'))); + + // Check the uploadprogress extension is loaded. + if (extension_loaded('uploadprogress')) { + $value = t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)'); + $description = NULL; + } + else { + $value = t('Not enabled'); + $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.'); + } - if (!$is_apache && !$is_nginx) { - $value = t('Not enabled'); - $description = t('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php or Nginx with PHP-FPM.'); - } - elseif ($fastcgi) { - $value = t('Not enabled'); - $description = t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.'); - } - elseif (!$implementation) { - $value = t('Not enabled'); - $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.'); - } - elseif ($implementation == 'uploadprogress') { - $value = t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)'); - } - $requirements['file_progress'] = [ - 'title' => t('Upload progress'), - 'value' => $value, - 'description' => $description, - ]; + // Adjust the requirement depending on what the server supports. + if (!$is_apache && !$is_nginx) { + $value = t('Not enabled'); + $description = t('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php or Nginx with PHP-FPM.'); + } + elseif ($fastcgi) { + $value = t('Not enabled'); + $description = t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.'); } + $requirements['file_progress'] = [ + 'title' => t('Upload progress'), + 'value' => $value, + 'description' => $description, + ]; + return $requirements; } diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 605add68df73..997879636e87 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -723,8 +723,14 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL * @return string|false * A string indicating which upload progress system is available. Either "apc" * or "uploadprogress". If neither are available, returns FALSE. + * + * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use + * extension_loaded('uploadprogress') instead. + * + * @see https://www.drupal.org/node/3397577 */ function file_progress_implementation() { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use extension_loaded(\'uploadprogress\') instead. See https://www.drupal.org/node/3397577', E_USER_DEPRECATED); static $implementation; if (!isset($implementation)) { $implementation = FALSE; diff --git a/core/modules/file/src/Controller/FileWidgetAjaxController.php b/core/modules/file/src/Controller/FileWidgetAjaxController.php index 098337887a94..f27836c2154a 100644 --- a/core/modules/file/src/Controller/FileWidgetAjaxController.php +++ b/core/modules/file/src/Controller/FileWidgetAjaxController.php @@ -27,8 +27,7 @@ public function progress($key) { 'percentage' => -1, ]; - $implementation = file_progress_implementation(); - if ($implementation == 'uploadprogress') { + if (extension_loaded('uploadprogress')) { $status = uploadprogress_get_info($key); if (isset($status['bytes_uploaded']) && !empty($status['bytes_total'])) { $progress['message'] = t('Uploading... (@current of @total)', [ diff --git a/core/modules/file/src/Element/ManagedFile.php b/core/modules/file/src/Element/ManagedFile.php index 8056c16da9e4..a27740b6b86e 100644 --- a/core/modules/file/src/Element/ManagedFile.php +++ b/core/modules/file/src/Element/ManagedFile.php @@ -276,19 +276,17 @@ public static function processManagedFile(&$element, FormStateInterface $form_st ]; // Add progress bar support to the upload if possible. - if ($element['#progress_indicator'] == 'bar' && $implementation = file_progress_implementation()) { + if ($element['#progress_indicator'] == 'bar' && extension_loaded('uploadprogress')) { $upload_progress_key = mt_rand(); - if ($implementation == 'uploadprogress') { - $element['UPLOAD_IDENTIFIER'] = [ - '#type' => 'hidden', - '#value' => $upload_progress_key, - '#attributes' => ['class' => ['file-progress']], - // Uploadprogress extension requires this field to be at the top of - // the form. - '#weight' => -20, - ]; - } + $element['UPLOAD_IDENTIFIER'] = [ + '#type' => 'hidden', + '#value' => $upload_progress_key, + '#attributes' => ['class' => ['file-progress']], + // Uploadprogress extension requires this field to be at the top of + // the form. + '#weight' => -20, + ]; // Add the upload progress callback. $element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress', ['key' => $upload_progress_key]); diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php index c97a4d20b389..458d4234bc5b 100644 --- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php +++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php @@ -72,7 +72,7 @@ public function settingsForm(array $form, FormStateInterface $form_state) { '#default_value' => $this->getSetting('progress_indicator'), '#description' => $this->t('The throbber display does not show the status of uploads but takes up less space. The progress bar is helpful for monitoring progress on large uploads.'), '#weight' => 16, - '#access' => file_progress_implementation(), + '#access' => extension_loaded('uploadprogress'), ]; return $element; } diff --git a/core/modules/file/tests/src/Kernel/LegacyFileModuleTest.php b/core/modules/file/tests/src/Kernel/LegacyFileModuleTest.php new file mode 100644 index 000000000000..88eb01bdc675 --- /dev/null +++ b/core/modules/file/tests/src/Kernel/LegacyFileModuleTest.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\file\Kernel; + +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests file module deprecations. + * + * @group legacy + * @group file + */ +class LegacyFileModuleTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['file']; + + /** + * @covers ::file_progress_implementation + */ + public function testFileProgressDeprecation() { + $this->expectDeprecation('file_progress_implementation() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use extension_loaded(\'uploadprogress\') instead. See https://www.drupal.org/node/3397577'); + $this->assertFalse(\file_progress_implementation()); + } + +} diff --git a/core/modules/file/tests/src/Kernel/RequirementsTest.php b/core/modules/file/tests/src/Kernel/RequirementsTest.php new file mode 100644 index 000000000000..4d472644dc4b --- /dev/null +++ b/core/modules/file/tests/src/Kernel/RequirementsTest.php @@ -0,0 +1,80 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\file\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; + +/** + * Tests the file requirements. + * + * @group file + */ +class RequirementsTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['file']; + + /** + * Tests the file upload requirements. + */ + public function testUploadRequirements(): void { + if (\extension_loaded('uploadprogress')) { + $this->markTestSkipped('We are testing only when the uploadprogress extension is not loaded.'); + } + + /** @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler */ + $moduleHandler = $this->container->get('module_handler'); + $moduleHandler->loadInclude('file', 'install'); + + // Test unspecified server software. + $this->setServerSoftware(NULL); + $requirements = \file_requirements('runtime'); + $this->assertNotEmpty($requirements); + + $this->assertEquals('Upload progress', (string) $requirements['file_progress']['title']); + $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']); + $this->assertEquals('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php or Nginx with PHP-FPM.', (string) $requirements['file_progress']['description']); + + // Test Apache + mod_php. + $this->setServerSoftware('Apache mod_php'); + $requirements = \file_requirements('runtime'); + $this->assertNotEmpty($requirements); + $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']); + $this->assertEquals('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.', (string) $requirements['file_progress']['description']); + + // Test Apache + mod_fastcgi. + $this->setServerSoftware('Apache mod_fastcgi'); + $requirements = \file_requirements('runtime'); + $this->assertNotEmpty($requirements); + $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']); + $this->assertEquals('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.', (string) $requirements['file_progress']['description']); + + // Test Nginx. + $this->setServerSoftware('Nginx'); + $requirements = \file_requirements('runtime'); + $this->assertNotEmpty($requirements); + $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']); + $this->assertEquals('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.', (string) $requirements['file_progress']['description']); + + } + + /** + * Sets the server software attribute in the request. + */ + private function setServerSoftware(?string $software): void { + $request = new Request(); + if (is_string($software)) { + $request->server->set('SERVER_SOFTWARE', $software); + } + $requestStack = new RequestStack(); + $requestStack->push($request); + $this->container->set('request_stack', $requestStack); + } + +} diff --git a/core/phpstan-baseline.neon b/core/phpstan-baseline.neon index a37bb883d881..5079add152b2 100644 --- a/core/phpstan-baseline.neon +++ b/core/phpstan-baseline.neon @@ -1446,11 +1446,6 @@ parameters: count: 1 path: modules/field_ui/src/Form/FieldStorageConfigEditForm.php - - - message: "#^Variable \\$value might not be defined\\.$#" - count: 1 - path: modules/file/file.install - - message: "#^Variable \\$file_upload in empty\\(\\) always exists and is not falsy\\.$#" count: 1 -- GitLab