Skip to content

Commit 0c7a01c

Browse files
authored
Merge pull request #261 from Xpirix/match_plugins_count
Match plugins count in XML with QGIS 4 Ready List
2 parents 4c3f49e + cd0652a commit 0c7a01c

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

qgis-app/plugins/models.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ class BasePluginManager(models.Manager):
3333
* weighted_rating uses the Bayesian Average formula
3434
to provide a more balanced rating that mitigates the effect of low vote counts.
3535
36-
Excludes soft-deleted plugins by default.
36+
Includes soft-deleted plugins so they remain visible in listings until
37+
permanently deleted.
3738
"""
3839

3940
def get_queryset(self):
4041
return (
4142
super(BasePluginManager, self)
4243
.get_queryset()
43-
.filter(is_deleted=False)
4444
.extra(
4545
select={
4646
"average_vote": "rating_score / (rating_votes + 0.001)",
@@ -121,7 +121,6 @@ def get_queryset(self):
121121
.filter(
122122
pluginversion__approved=True,
123123
pluginversion__max_qg_version__gte=f"{settings.NEW_QGIS_MAJOR_VERSION}.0",
124-
deprecated=False
125124
)
126125
.distinct()
127126
.order_by("-created_on")
@@ -204,7 +203,7 @@ def get_queryset(self):
204203
return (
205204
super(UnapprovedPlugins, self)
206205
.get_queryset()
207-
.filter(pluginversion__approved=False, deprecated=False)
206+
.filter(pluginversion__approved=False, deprecated=False, is_deleted=False)
208207
.extra(
209208
select={
210209
"average_vote": "rating_score / (rating_votes + 0.001)",

qgis-app/plugins/search_indexes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ def get_model(self):
2626
return Plugin
2727

2828
def index_queryset(self, using=None):
29-
"""Only search in approved plugins."""
29+
"""Search in approved plugins, including those marked for deletion."""
3030
return Plugin.approved_objects.all()

qgis-app/plugins/tests/test_soft_delete.py

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,12 @@ def test_plugin_soft_delete_marks_as_deleted(self):
7676
self.assertTrue(plugin.is_deleted)
7777
self.assertIsNotNone(plugin.deleted_on)
7878

79-
def test_soft_deleted_plugin_excluded_from_approved_objects(self):
80-
"""Test that soft-deleted plugins don't appear in approved_objects."""
79+
def test_soft_deleted_plugin_still_in_approved_objects(self):
80+
"""Test that soft-deleted plugins still appear in approved_objects.
81+
82+
Plugins marked for deletion should remain visible in the public listing
83+
until they are permanently deleted (see issue #253).
84+
"""
8185
# First, approve and verify plugin appears
8286
self.version1.approved = True
8387
self.version1.save()
@@ -88,8 +92,8 @@ def test_soft_deleted_plugin_excluded_from_approved_objects(self):
8892
self.plugin.deleted_on = timezone.now()
8993
self.plugin.save()
9094

91-
# Plugin should not appear in approved_objects
92-
self.assertNotIn(self.plugin, Plugin.approved_objects.all())
95+
# Plugin should still appear in approved_objects (visible in listings)
96+
self.assertIn(self.plugin, Plugin.approved_objects.all())
9397

9498
def test_soft_deleted_plugin_visible_in_my_plugins(self):
9599
"""Test that soft-deleted plugins are visible to owners in My Plugins."""
@@ -162,6 +166,44 @@ def test_only_soft_deleted_plugins_can_be_permanently_deleted(self):
162166
# Should get 404
163167
self.assertEqual(response.status_code, 404)
164168

169+
def test_soft_deleted_plugin_visible_in_approved_listing(self):
170+
"""Test that soft-deleted plugins still appear in the approved plugin listing.
171+
172+
Plugins marked for deletion remain accessible until permanently deleted
173+
so users can still download them during the grace period (see issue #253).
174+
"""
175+
# Approve the version so plugin appears in approved listing
176+
self.version1.approved = True
177+
self.version1.save()
178+
self.assertIn(self.plugin, Plugin.approved_objects.all())
179+
180+
# Soft delete the plugin
181+
self.plugin.is_deleted = True
182+
self.plugin.deleted_on = timezone.now()
183+
self.plugin.save()
184+
185+
# Plugin should still appear in approved_objects listing
186+
self.assertIn(self.plugin, Plugin.approved_objects.all())
187+
188+
# Check it also appears in the view response
189+
response = self.client.get(reverse("approved_plugins"))
190+
self.assertEqual(response.status_code, 200)
191+
self.assertContains(response, self.plugin.name)
192+
193+
def test_soft_deleted_plugin_excluded_from_unapproved_listing(self):
194+
"""Test that soft-deleted plugins don't appear in the unapproval queue."""
195+
# version2 is unapproved, so the plugin appears in unapproved_objects
196+
self.assertIn(self.plugin, Plugin.unapproved_objects.all())
197+
198+
# Soft delete the plugin
199+
self.plugin.is_deleted = True
200+
self.plugin.deleted_on = timezone.now()
201+
self.plugin.save()
202+
203+
# Plugin should NOT appear in unapproved_objects (no need to review
204+
# plugins that are being deleted)
205+
self.assertNotIn(self.plugin, Plugin.unapproved_objects.all())
206+
165207

166208
class TestDeleteMarkedPluginsTask(SetupMixin, TestCase):
167209
"""Test the Celery task for permanent deletion of marked plugins."""

0 commit comments

Comments
 (0)