diff --git a/openedx_learning/apps/authoring/backup_restore/toml.py b/openedx_learning/apps/authoring/backup_restore/toml.py index 05ede1df3..0551201ba 100644 --- a/openedx_learning/apps/authoring/backup_restore/toml.py +++ b/openedx_learning/apps/authoring/backup_restore/toml.py @@ -6,11 +6,8 @@ import tomlkit +from openedx_learning.apps.authoring.publishing.models import PublishableEntity, PublishableEntityVersion from openedx_learning.apps.authoring.publishing.models.learning_package import LearningPackage -from openedx_learning.apps.authoring.publishing.models.publishable_entity import ( - PublishableEntityMixin, - PublishableEntityVersionMixin, -) def toml_learning_package(learning_package: LearningPackage) -> str: @@ -27,29 +24,34 @@ def toml_learning_package(learning_package: LearningPackage) -> str: return tomlkit.dumps(doc) -def toml_publishable_entity(entity: PublishableEntityMixin) -> str: +def toml_publishable_entity(entity: PublishableEntity) -> str: """Create a TOML representation of a publishable entity.""" + + current_draft_version = getattr(entity, "draft", None) + current_published_version = getattr(entity, "published", None) + doc = tomlkit.document() entity_table = tomlkit.table() entity_table.add("uuid", str(entity.uuid)) entity_table.add("can_stand_alone", entity.can_stand_alone) - draft = tomlkit.table() - draft.add("version_num", entity.versioning.draft.version_num) - entity_table.add("draft", draft) + if current_draft_version: + draft_table = tomlkit.table() + draft_table.add("version_num", current_draft_version.version.version_num) + entity_table.add("draft", draft_table) - published = tomlkit.table() - if entity.versioning.published: - published.add("version_num", entity.versioning.published.version_num) + published_table = tomlkit.table() + if current_published_version: + published_table.add("version_num", current_published_version.version.version_num) else: - published.add(tomlkit.comment("unpublished: no published_version_num")) - entity_table.add("published", published) + published_table.add(tomlkit.comment("unpublished: no published_version_num")) + entity_table.add("published", published_table) doc.add("entity", entity_table) doc.add(tomlkit.nl()) doc.add(tomlkit.comment("### Versions")) - for entity_version in entity.versioning.versions.all(): + for entity_version in entity.versions.all(): version = tomlkit.aot() version_table = toml_publishable_entity_version(entity_version) version.append(version_table) @@ -58,7 +60,7 @@ def toml_publishable_entity(entity: PublishableEntityMixin) -> str: return tomlkit.dumps(doc) -def toml_publishable_entity_version(version: PublishableEntityVersionMixin) -> tomlkit.items.Table: +def toml_publishable_entity_version(version: PublishableEntityVersion) -> tomlkit.items.Table: """Create a TOML representation of a publishable entity version.""" version_table = tomlkit.table() version_table.add("title", version.title) diff --git a/openedx_learning/apps/authoring/backup_restore/zipper.py b/openedx_learning/apps/authoring/backup_restore/zipper.py index 2c07401e5..8ea73c71e 100644 --- a/openedx_learning/apps/authoring/backup_restore/zipper.py +++ b/openedx_learning/apps/authoring/backup_restore/zipper.py @@ -6,7 +6,7 @@ from pathlib import Path from openedx_learning.apps.authoring.backup_restore.toml import toml_learning_package, toml_publishable_entity -from openedx_learning.apps.authoring.components import api as components_api +from openedx_learning.apps.authoring.publishing import api as publishing_api from openedx_learning.apps.authoring.publishing.models.learning_package import LearningPackage TOML_PACKAGE_NAME = "package.toml" @@ -45,7 +45,7 @@ def create_zip(self, path: str) -> None: zipf.writestr(collections_info, "") # Add explicit empty directory # Add each entity's TOML file - for entity in components_api.get_components(self.learning_package.pk): + for entity in publishing_api.get_entities(self.learning_package.pk): # Create a TOML representation of the entity entity_toml_content: str = toml_publishable_entity(entity) entity_toml_filename = f"{entity.key}.toml" diff --git a/openedx_learning/apps/authoring/publishing/api.py b/openedx_learning/apps/authoring/publishing/api.py index 388f52cba..871df8e25 100644 --- a/openedx_learning/apps/authoring/publishing/api.py +++ b/openedx_learning/apps/authoring/publishing/api.py @@ -60,6 +60,7 @@ "get_publishable_entity_by_key", "get_last_publish", "get_all_drafts", + "get_entities", "get_entities_with_unpublished_changes", "get_entities_with_unpublished_deletes", "publish_all_drafts", @@ -261,6 +262,13 @@ def get_all_drafts(learning_package_id: int, /) -> QuerySet[Draft]: ) +def get_entities(learning_package_id: int, /) -> QuerySet[PublishableEntity]: + """ + Get all entities in a learning package. + """ + return PublishableEntity.objects.filter(learning_package_id=learning_package_id) + + def get_entities_with_unpublished_changes( learning_package_id: int, /, diff --git a/tests/openedx_learning/apps/authoring/publishing/test_api.py b/tests/openedx_learning/apps/authoring/publishing/test_api.py index b9e45ec91..94c328f22 100644 --- a/tests/openedx_learning/apps/authoring/publishing/test_api.py +++ b/tests/openedx_learning/apps/authoring/publishing/test_api.py @@ -1075,3 +1075,65 @@ def test_multiple_layers_of_containers(self): assert unit_change.affected_by.first().cause == component_change assert subsection_change.affected_by.count() == 1 assert subsection_change.affected_by.first().cause == unit_change + + +class EntitiesQueryTestCase(TestCase): + """ + Tests for querying PublishableEntity objects. + """ + now: datetime + learning_package_1: LearningPackage + learning_package_2: LearningPackage + + @classmethod + def setUpTestData(cls) -> None: + cls.now = datetime(2025, 8, 4, 12, 00, 00, tzinfo=timezone.utc) + cls.learning_package_1 = publishing_api.create_learning_package( + "my_package_key_1", + "Entities Testing LearningPackage 🔥 1", + created=cls.now, + ) + cls.learning_package_2 = publishing_api.create_learning_package( + "my_package_key_2", + "Entities Testing LearningPackage 🔥 2", + created=cls.now, + ) + + def test_get_entities(self) -> None: + """ + Test that get_entities returns all entities for a learning package. + """ + with publishing_api.bulk_draft_changes_for(self.learning_package_1.id): + entity = publishing_api.create_publishable_entity( + self.learning_package_1.id, + "my_entity", + created=self.now, + created_by=None, + ) + publishing_api.create_publishable_entity_version( + entity.id, + version_num=1, + title="An Entity 🌴", + created=self.now, + created_by=None, + ) + entity2 = publishing_api.create_publishable_entity( + self.learning_package_1.id, + "my_entity2", + created=self.now, + created_by=None, + ) + publishing_api.create_publishable_entity_version( + entity2.id, + version_num=1, + title="An Entity 🌴 2", + created=self.now, + created_by=None, + ) + entities = publishing_api.get_entities(self.learning_package_1.id) + assert entities.count() == 2 + for entity in entities: + assert isinstance(entity, PublishableEntity) + assert entity.learning_package_id == self.learning_package_1.id + assert entity.created == self.now + assert entity.created_by is None