Repository: zestedesavoir/zds-site

Issue:
Prise en compte du champ ready_to_publish lors des imports
**Description du bug**

Lors de l'import du contenu (quel qu'il soit) avec le mécanisme « Importer une nouvelle version », les valeurs données à la clé `"ready_to_publish"` dans le fichier `manifest.json` sont ignorées.

**Comment reproduire ?**

1. Allez sur le site, créez un contenu quelconque : dans mon exemple un big tuto avec 2 parties et 3 chapitres <https://beta.zestedesavoir.com/contenus/3960/trucmuch/>
2. Téléchargez l'archive du contenu (<https://beta.zestedesavoir.com/contenus/telecharger/3960/trucmuch/>)
    - Dans mon cas le fichier `manifest.json` est le suivant : https://gist.github.com/entwanne/187119d4cc9da26142267ce0d8303f69#file-manifest-json_1
3. Modifiez cette archive afin de passer des clés `"ready_to_publish"` à `false` dans le `manifest.json`
    - Mon `manifest.json` modifié est ici : <https://gist.github.com/entwanne/187119d4cc9da26142267ce0d8303f69#file-manifest-json_2>, j'ai désactivé un chapitre et une partie.
4. Importez cette nouvelle version du contenu
5. Constatez que rien n'a changé, tous les chapitres et parties sont encore indiqués comme à valider
6. Téléchargez l'archive du contenu pour constater que tous les `"ready_to_publish"` y sont à `true`.

**Comportement attendu**

L'import d'une nouvelle version aurait dû marquer comme « à ne pas valider » mon chapitre 2 et ma partie 2.

**Capture d'écran**

![Partie 2](https://zestedesavoir.com/media/galleries/5661/0daa42ae-aaf5-42d0-8526-fcf3361629d1.png)

La partie 2 n'est pas marquée comme « à ne pas valider »

**Informations techniques**

Le problème est visible sur la version courante (`v30.1c-artemis`) comme sur la bêta (`dev/01ee0fa`).
Je suis personnellement sur Linux avec Chromium 94 mais je ne pense pas que ça joue.


Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/archives.py b/zds/tutorialv2/views/archives.py
--- a/zds/tutorialv2/views/archives.py
+++ b/zds/tutorialv2/views/archives.py
@@ -198,6 +198,8 @@ def update_from_new_version_in_zip(copy_to, copy_from, zip_file):
                         raise BadArchiveError(_(f"Le fichier « {child.conclusion} » n'est pas encodé en UTF-8"))
 
                 copy_to.repo_add_container(child.title, introduction, conclusion, do_commit=False, slug=child.slug)
+                copy_to.children[-1].ready_to_publish = child.ready_to_publish
+                copy_to.repo_update(copy_to.title, introduction, conclusion, do_commit=False)
                 UpdateContentWithArchive.update_from_new_version_in_zip(copy_to.children[-1], child, zip_file)
 
             elif isinstance(child, Extract):
@@ -381,6 +383,7 @@ def form_valid(self, form):
                 if new_version.conclusion:
                     conclusion = str(zfile.read(new_version.conclusion), "utf-8")
 
+                versioned.ready_to_publish = new_version.ready_to_publish
                 versioned.repo_update_top_container(
                     new_version.title, new_version.slug, introduction, conclusion, do_commit=False
                 )


Test patch:
diff --git a/zds/tutorialv2/tests/tests_views/tests_content.py b/zds/tutorialv2/tests/tests_views/tests_content.py
--- a/zds/tutorialv2/tests/tests_views/tests_content.py
+++ b/zds/tutorialv2/tests/tests_views/tests_content.py
@@ -1634,7 +1634,7 @@ def test_import_in_existing_content(self):
 
         # ensure the content
         self.assertEqual(versioned.get_introduction(), some_text)
-        self.assertEqual(versioned.get_introduction(), some_text)
+        self.assertEqual(versioned.get_conclusion(), some_text)
         self.assertEqual(len(versioned.children), 1)
 
         new_chapter = versioned.children[-1]
@@ -1774,6 +1774,59 @@ def test_import_image_with_archive(self):
         os.remove(draft_zip_path)
         os.remove(image_zip_path)
 
+    def test_import_ready_to_publish(self):
+        """Test whether the 'ready_to_publish' info from the archive is correctly imported."""
+
+        # General principle of this test:
+        #   * create an archive by creating a content and exporting it
+        #   * change the 'ready_to_publish' toggles on the content
+        #   * import the archive and check whether we get back to the initial state (i.e. correct import)
+
+        self.client.force_login(self.user_author)
+
+        # Create a content with parts
+        content = PublishableContentFactory(author_list=[self.user_author])
+        versioned = content.load_version()
+        part1 = ContainerFactory(db_object=content, parent=versioned)
+        chapter1 = ContainerFactory(db_object=content, parent=part1)
+        chapter1.ready_to_publish = False
+        ContainerFactory(db_object=content, parent=part1)  # chapter 2
+        part2 = ContainerFactory(db_object=content, parent=versioned)
+        part2.ready_to_publish = False
+        sha = versioned.repo_update(content.title, content.slug, "introduction", "conclusion")
+        content.sha_draft = sha
+        content.save()
+
+        # Download archive of initial state for content
+        result = self.client.get(reverse("content:download-zip", args=[content.pk, content.slug]), follow=False)
+        self.assertEqual(result.status_code, 200)
+        draft_zip_path = os.path.join(tempfile.gettempdir(), "__draft1.zip")
+        with open(draft_zip_path, "wb") as f:
+            f.write(result.content)
+
+        # Update readiness of part 2 and part1/chapter1
+        # Failure to import this information defaults also to True, this is to make sure.
+        versioned.children[0].children[0].ready_to_publish = True
+        versioned.children[1].ready_to_publish = True
+        sha = versioned.repo_update_top_container(content.title, content.slug, "introduction", "conclusion")
+        content.sha_draft = sha
+        content.save()
+
+        # Import archive
+        result = self.client.post(
+            reverse("content:import", args=[content.pk, content.slug]),
+            {"archive": open(draft_zip_path, "rb")},
+        )
+        self.assertEqual(result.status_code, 302)
+
+        # Check override of previous modifications through the import
+        content = PublishableContent.objects.get(pk=content.pk)  # reload from database
+        versioned = content.load_version()
+        self.assertTrue(versioned.children[0].ready_to_publish)
+        self.assertTrue(versioned.children[0].children[1].ready_to_publish)
+        self.assertFalse(versioned.children[0].children[0].ready_to_publish)
+        self.assertFalse(versioned.children[1].ready_to_publish)
+
     def test_display_history(self):
         """Test DisplayHistory view"""