Ejemplo n.º 1
0
    def get_published_content_entity(self, md_file_path):
        """
        Retrieve the db entity from mdfile path

        :param md_file_path: mdfile path as string
        :type md_file_path: str
        :return: the db entity
        :rtype: zds.tutorialv2.models.models_database.PublishedContent
        """
        content_slug = PublishedContent.get_slug_from_file_path(md_file_path)
        published_content_entity = PublishedContent.objects.filter(content_public_slug=content_slug).first()
        return published_content_entity
Ejemplo n.º 2
0
    def get_published_content_entity(self, md_file_path):
        """
        Retrieve the db entity from mdfile path

        :param md_file_path: mdfile path as string
        :type md_file_path: str
        :return: the db entity
        :rtype: zds.tutorialv2.models.models_database.PublishedContent
        """
        content_slug = PublishedContent.get_slug_from_file_path(md_file_path)
        published_content_entity = PublishedContent.objects \
            .filter(content_public_slug=content_slug) \
            .first()
        return published_content_entity
Ejemplo n.º 3
0
def update_existing_publication(db_object, versioned):
    public_version = db_object.public_version
    # the content has been published in the past, so clean up old files!
    old_path = public_version.get_prod_path()
    logging.getLogger(__name__).debug("erase " + old_path)
    shutil.rmtree(old_path)
    # if the slug has changed, create a new object instead of reusing the old one
    # this allows us to handle permanent redirection so that SEO is not impacted.
    if versioned.slug != public_version.content_public_slug:
        public_version.must_redirect = True  # set redirection
        public_version.save(update_fields=["must_redirect"])
        publication_date = public_version.publication_date
        db_object.public_version = PublishedContent()
        public_version = db_object.public_version

        # keep the same publication date if the content is already published
        public_version.publication_date = publication_date
    return True, public_version
Ejemplo n.º 4
0
def publish_content(db_object, versioned, is_major_update=True):
    """
    Publish a given content.

    .. note::
        create a manifest.json without the introduction and conclusion if not needed. Also remove the 'text' field
        of extracts.

    :param db_object: Database representation of the content
    :type db_object: zds.tutorialv2.models.database.PublishableContent
    :param versioned: version of the content to publish
    :type versioned: zds.tutorialv2.models.versioned.VersionedContent
    :param is_major_update: if set to `True`, will update the publication date
    :type is_major_update: bool
    :raise FailureDuringPublication: if something goes wrong
    :return: the published representation
    :rtype: zds.tutorialv2.models.database.PublishedContent
    """

    from zds.tutorialv2.models.database import PublishedContent

    if is_major_update:
        versioned.pubdate = datetime.now()

    # First write the files to a temporary directory: if anything goes wrong,
    # the last published version is not impacted !
    tmp_path = path.join(settings.ZDS_APP["content"]["repo_public_path"], versioned.slug + "__building")
    if path.exists(tmp_path):
        shutil.rmtree(tmp_path)  # remove previous attempt, if any

    # render HTML:
    altered_version = copy.deepcopy(versioned)
    publish_container(db_object, tmp_path, altered_version)
    altered_version.dump_json(path.join(tmp_path, "manifest.json"))

    # make room for 'extra contents'
    build_extra_contents_path = path.join(tmp_path, settings.ZDS_APP["content"]["extra_contents_dirname"])
    makedirs(build_extra_contents_path)
    base_name = path.join(build_extra_contents_path, versioned.slug)

    # 1. markdown file (base for the others) :
    # If we come from a command line, we need to activate i18n, to have the date in the french language.
    cur_language = translation.get_language()
    altered_version.pubdate = datetime.now()

    md_file_path = base_name + ".md"
    with contextlib.suppress(OSError):
        Path(Path(md_file_path).parent, "images").mkdir()
    is_update = False

    if db_object.public_version:
        is_update, public_version = update_existing_publication(db_object, versioned)
    else:
        public_version = PublishedContent()

    # make the new public version
    public_version.content_public_slug = versioned.slug
    public_version.content_type = versioned.type
    public_version.content_pk = db_object.pk
    public_version.content = db_object
    public_version.must_reindex = True
    public_version.save()
    with contextlib.suppress(FileExistsError):
        makedirs(public_version.get_extra_contents_directory())
    PublicatorRegistry.get("md").publish(md_file_path, base_name, versioned=versioned, cur_language=cur_language)
    public_version.char_count = public_version.get_char_count(md_file_path)
    if is_major_update or not is_update:
        public_version.publication_date = datetime.now()
    elif is_update:
        public_version.update_date = datetime.now()
    public_version.sha_public = versioned.current_version
    public_version.save()
    with contextlib.suppress(OSError):
        make_zip_file(public_version)

    public_version.save(update_fields=["char_count", "publication_date", "update_date", "sha_public"])

    public_version.authors.clear()
    for author in db_object.authors.all():
        public_version.authors.add(author)

    # this puts the manifest.json and base json file on the prod path.
    shutil.rmtree(public_version.get_prod_path(), ignore_errors=True)
    shutil.copytree(tmp_path, public_version.get_prod_path())
    if settings.ZDS_APP["content"]["extra_content_generation_policy"] == "SYNC":
        # ok, now we can really publish the thing!
        generate_external_content(base_name, build_extra_contents_path, md_file_path)
    elif settings.ZDS_APP["content"]["extra_content_generation_policy"] == "WATCHDOG":
        PublicatorRegistry.get("watchdog").publish(md_file_path, base_name, silently_pass=False)
    db_object.sha_public = versioned.current_version
    return public_version
Ejemplo n.º 5
0
    def test_special_case_of_contents(self):
        """test that the old publishedcontent does not stay when a new one is created"""

        if not self.manager.connected_to_es:
            return

        # 1. Create a middle-tutorial, publish it, then index it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        ExtractFactory(container=chapter1, db_object=tuto)
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True)  # index
        self.manager.refresh_index()

        first_publication = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(first_publication.es_already_indexed)
        self.assertFalse(first_publication.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)  # get 2 results, one for the content and one for the chapter

        self.assertEqual(PublishedContent.objects.count(), 1)

        # 2. Change thet title, which will trigger a change in the slug
        tuto = PublishableContent.objects.get(pk=tuto.pk)
        versioned = tuto.load_version(sha=tuto.sha_draft)

        tuto.title = 'un titre complètement différent!'
        tuto.save()

        versioned.repo_update_top_container(tuto.title, tuto.slug, 'osef', 'osef')
        second_publication = publish_content(tuto, versioned, True)

        tuto.sha_public = versioned.current_version
        tuto.sha_draft = versioned.current_version
        tuto.public_version = second_publication
        tuto.save()

        self.assertEqual(PublishedContent.objects.count(), 2)  # now there is two objects ...
        first_publication = PublishedContent.objects.get(pk=first_publication.pk)
        self.assertTrue(first_publication.must_redirect)  # .. including the first one, for redirection

        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 0)  # the old one is gone (and we need to reindex to get the new one)

        # 3. Check if indexation brings the new one, and not the old one
        self.manager.es_bulk_indexing_of_model(PublishedContent, force_reindexing=True)  # index
        self.manager.refresh_index()

        first_publication = PublishedContent.objects.get(pk=first_publication.pk)
        second_publication = PublishedContent.objects.get(pk=second_publication.pk)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)  # Still 2, not 4 !

        found_old = False
        found_new = False

        for hit in results:
            if hit.meta.doc_type == PublishedContent.get_es_document_type():
                if hit.meta.id == first_publication.es_id:
                    found_old = True
                if hit.meta.id == second_publication.es_id:
                    found_new = True

        self.assertTrue(found_new)
        self.assertFalse(found_old)
Ejemplo n.º 6
0
def publish_content(db_object, versioned, is_major_update=True):
    """
    Publish a given content.

    .. note::
        create a manifest.json without the introduction and conclusion if not needed. Also remove the 'text' field
        of extracts.

    :param db_object: Database representation of the content
    :type db_object: PublishableContent
    :param versioned: version of the content to publish
    :type versioned: VersionedContent
    :param is_major_update: if set to `True`, will update the publication date
    :type is_major_update: bool
    :raise FailureDuringPublication: if something goes wrong
    :return: the published representation
    :rtype: zds.tutorialv2.models.database.PublishedContent
    """

    from zds.tutorialv2.models.database import PublishedContent

    if is_major_update:
        versioned.pubdate = datetime.now()

    # First write the files in a temporary directory: if anything goes wrong,
    # the last published version is not impacted !
    tmp_path = os.path.join(settings.ZDS_APP['content']['repo_public_path'],
                            versioned.slug + '__building')

    if os.path.exists(tmp_path):
        shutil.rmtree(tmp_path)  # erase previous attempt, if any

    # render HTML:
    altered_version = copy.deepcopy(versioned)
    publish_container(db_object, tmp_path, altered_version)
    altered_version.dump_json(os.path.join(tmp_path, 'manifest.json'))

    # make room for 'extra contents'
    extra_contents_path = os.path.join(
        tmp_path, settings.ZDS_APP['content']['extra_contents_dirname'])
    os.makedirs(extra_contents_path)

    base_name = os.path.join(extra_contents_path, versioned.slug)

    # 1. markdown file (base for the others) :
    # If we come from a command line, we need to activate i18n, to have the date in the french language.
    cur_language = translation.get_language()
    versioned.pubdate = datetime.now()
    try:
        translation.activate(settings.LANGUAGE_CODE)
        parsed = render_to_string('tutorialv2/export/content.md',
                                  {'content': versioned})
    finally:
        translation.activate(cur_language)

    parsed_with_local_images = retrieve_and_update_images_links(
        parsed, directory=extra_contents_path)

    md_file_path = base_name + '.md'
    md_file = codecs.open(md_file_path, 'w', encoding='utf-8')
    try:
        md_file.write(parsed_with_local_images)
    except (UnicodeError, UnicodeEncodeError):
        raise FailureDuringPublication(
            _('Une erreur est survenue durant la génération du fichier markdown '
              'à télécharger, vérifiez le code markdown'))
    finally:
        md_file.close()

    pandoc_debug_str = ''
    if settings.PANDOC_LOG_STATE:
        pandoc_debug_str = ' 2>&1 | tee -a ' + settings.PANDOC_LOG
    if settings.ZDS_APP['content'][
            'extra_content_generation_policy'] == 'SYNC':
        # ok, now we can really publish the thing !
        generate_exernal_content(base_name, extra_contents_path, md_file_path,
                                 pandoc_debug_str)
    elif settings.ZDS_APP['content'][
            'extra_content_generation_policy'] == 'WATCHDOG':
        PublicatorRegistery.get('watchdog').publish(md_file_path,
                                                    base_name,
                                                    silently_pass=False)

    is_update = False

    if db_object.public_version:
        public_version = db_object.public_version
        is_update = True

        # the content have been published in the past, so clean old files !
        old_path = public_version.get_prod_path()
        shutil.rmtree(old_path)

        # if the slug change, instead of using the same object, a new one will be created
        if versioned.slug != public_version.content_public_slug:
            public_version.must_redirect = True  # set redirection
            publication_date = public_version.publication_date
            public_version.save()
            db_object.public_version = PublishedContent()
            public_version = db_object.public_version

            # if content have already been published, keep publication date !
            public_version.publication_date = publication_date

    else:
        public_version = PublishedContent()

    # make the new public version
    public_version.content_public_slug = versioned.slug
    public_version.content_type = versioned.type
    public_version.content_pk = db_object.pk
    public_version.content = db_object
    public_version.must_reindex = True
    public_version.save()
    public_version.char_count = public_version.get_char_count(md_file_path)

    for author in db_object.authors.all():
        public_version.authors.add(author)
    public_version.save()
    # move the stuffs into the good position
    if settings.ZDS_APP['content'][
            'extra_content_generation_policy'] != 'WATCHDOG':
        shutil.move(tmp_path, public_version.get_prod_path())
    else:  # if we use watchdog, we use copy to get md and zip file in prod but everything else will be handled by
        # watchdog
        shutil.copytree(tmp_path, public_version.get_prod_path())
    # save public version
    if is_major_update or not is_update:
        public_version.publication_date = datetime.now()
    elif is_update:
        public_version.update_date = datetime.now()

    public_version.sha_public = versioned.current_version
    public_version.save()
    try:
        make_zip_file(public_version)
    except OSError:
        pass

    return public_version
Ejemplo n.º 7
0
def publish_content(db_object, versioned, is_major_update=True):
    """
    Publish a given content.

    .. note::
        create a manifest.json without the introduction and conclusion if not needed. Also remove the 'text' field
        of extracts.

    :param db_object: Database representation of the content
    :type db_object: zds.tutorialv2.models.database.PublishableContent
    :param versioned: version of the content to publish
    :type versioned: zds.tutorialv2.models.versioned.VersionedContent
    :param is_major_update: if set to `True`, will update the publication date
    :type is_major_update: bool
    :raise FailureDuringPublication: if something goes wrong
    :return: the published representation
    :rtype: zds.tutorialv2.models.database.PublishedContent
    """

    from zds.tutorialv2.models.database import PublishedContent

    if is_major_update:
        versioned.pubdate = datetime.now()

    # First write the files to a temporary directory: if anything goes wrong,
    # the last published version is not impacted !
    tmp_path = path.join(settings.ZDS_APP['content']['repo_public_path'], versioned.slug + '__building')
    if path.exists(tmp_path):
        shutil.rmtree(tmp_path)  # remove previous attempt, if any

    # render HTML:
    altered_version = copy.deepcopy(versioned)
    publish_container(db_object, tmp_path, altered_version)
    altered_version.dump_json(path.join(tmp_path, 'manifest.json'))

    # make room for 'extra contents'
    build_extra_contents_path = path.join(tmp_path, settings.ZDS_APP['content']['extra_contents_dirname'])
    makedirs(build_extra_contents_path)
    base_name = path.join(build_extra_contents_path, versioned.slug)

    # 1. markdown file (base for the others) :
    # If we come from a command line, we need to activate i18n, to have the date in the french language.
    cur_language = translation.get_language()
    altered_version.pubdate = datetime.now()

    md_file_path = base_name + '.md'
    with contextlib.suppress(OSError):
        Path(Path(md_file_path).parent, 'images').mkdir()
    is_update = False

    if db_object.public_version:
        is_update, public_version = update_existing_publication(db_object, versioned)
    else:
        public_version = PublishedContent()

    # make the new public version
    public_version.content_public_slug = versioned.slug
    public_version.content_type = versioned.type
    public_version.content_pk = db_object.pk
    public_version.content = db_object
    public_version.must_reindex = True
    public_version.save()
    with contextlib.suppress(FileExistsError):
        makedirs(public_version.get_extra_contents_directory())
    PublicatorRegistry.get('md').publish(md_file_path, base_name, versioned=versioned, cur_language=cur_language)
    public_version.char_count = public_version.get_char_count(md_file_path)
    if is_major_update or not is_update:
        public_version.publication_date = datetime.now()
    elif is_update:
        public_version.update_date = datetime.now()
    public_version.sha_public = versioned.current_version
    public_version.save()
    with contextlib.suppress(OSError):
        make_zip_file(public_version)

    public_version.save(
        update_fields=['char_count', 'publication_date', 'update_date', 'sha_public'])

    public_version.authors.clear()
    for author in db_object.authors.all():
        public_version.authors.add(author)

    # this puts the manifest.json and base json file on the prod path.
    shutil.rmtree(public_version.get_prod_path(), ignore_errors=True)
    shutil.copytree(tmp_path, public_version.get_prod_path())
    if settings.ZDS_APP['content']['extra_content_generation_policy'] == 'SYNC':
        # ok, now we can really publish the thing!
        generate_external_content(base_name, build_extra_contents_path, md_file_path)
    elif settings.ZDS_APP['content']['extra_content_generation_policy'] == 'WATCHDOG':
        PublicatorRegistry.get('watchdog').publish(md_file_path, base_name, silently_pass=False)
    db_object.sha_public = versioned.current_version
    return public_version