Ejemplo n.º 1
0
    def test_publish_view_post(self):
        """
        This posts to the publish view and checks that the page was published
        """
        # Connect a mock signal handler to page_published signal
        mock_handler = mock.MagicMock()
        page_published.connect(mock_handler)

        # Post to the publish page
        response = self.client.post(self.url)

        # Should be redirected to explorer page
        self.assertEqual(response.status_code, 302)

        # Check that the child pages were published
        for child_page in self.pages_to_be_published:
            self.assertTrue(Page.objects.get(id=child_page.id).live)

        # Check that the child pages not to be published remain
        for child_page in self.pages_not_to_be_published:
            self.assertFalse(Page.objects.get(id=child_page.id).live)

        # Check that the page_published signal was fired
        self.assertEqual(mock_handler.call_count,
                         len(self.pages_to_be_published))

        for i, child_page in enumerate(self.pages_to_be_published):
            mock_call = mock_handler.mock_calls[i][2]
            self.assertEqual(mock_call['sender'], child_page.specific_class)
            self.assertEqual(mock_call['instance'], child_page)
            self.assertIsInstance(mock_call['instance'],
                                  child_page.specific_class)
Ejemplo n.º 2
0
    def ready(self):
        from .handlers import event_published_handler
        from .models import EventPage, EventGeneralPage

        page_published.connect(event_published_handler, sender=EventPage)
        page_published.connect(event_published_handler, sender=EventGeneralPage)
        logger.info('event_published_handler should be connected now')
    def test_approve_moderation_view(self):
        """
        This posts to the approve moderation view and checks that the page was approved
        """
        # Connect a mock signal handler to page_published signal
        mock_handler = mock.MagicMock()
        page_published.connect(mock_handler)

        # Post
        response = self.client.post(
            reverse('wagtailadmin_pages:approve_moderation',
                    args=(self.revision.id, )))

        # Check that the user was redirected to the dashboard
        self.assertRedirects(response, reverse('wagtailadmin_home'))

        page = Page.objects.get(id=self.page.id)
        # Page must be live
        self.assertTrue(page.live,
                        "Approving moderation failed to set live=True")
        # Page should now have no unpublished changes
        self.assertFalse(
            page.has_unpublished_changes,
            "Approving moderation failed to set has_unpublished_changes=False")

        # Check that the page_published signal was fired
        self.assertEqual(mock_handler.call_count, 1)
        mock_call = mock_handler.mock_calls[0][2]

        self.assertEqual(mock_call['sender'], self.page.specific_class)
        self.assertEqual(mock_call['instance'], self.page)
        self.assertIsInstance(mock_call['instance'], self.page.specific_class)
Ejemplo n.º 4
0
def register_signal_handlers():
    # Get list of models that are page types
    Page = apps.get_model('wagtailcore', 'Page')
    indexed_models = [model for model in apps.get_models() if issubclass(model, Page)]

    # Loop through list and register signal handlers for each one
    for model in indexed_models:
        page_published.connect(page_published_signal_handler, sender=model)
        page_unpublished.connect(page_unpublished_signal_handler, sender=model)
Ejemplo n.º 5
0
 def subscribe(cls):
     for model_class in cls.model_classes:
         page_published.connect(
             receiver=cls.populate,
             sender=model_class,
             dispatch_uid=model_class.__name__,
         )
         page_unpublished.connect(
             receiver=cls.delete,
             sender=model_class,
             dispatch_uid=model_class.__name__,
         )
Ejemplo n.º 6
0
def register_signal_handlers():
    Image = get_image_model()
    Document = get_document_model()

    for model in get_page_models():
        page_published.connect(purge_page_from_cache, sender=model)
        page_unpublished.connect(purge_page_from_cache, sender=model)

    post_save.connect(purge_image_from_cache, sender=Image)
    post_delete.connect(purge_image_from_cache, sender=Image)
    post_save.connect(purge_document_from_cache, sender=Document)
    post_delete.connect(purge_document_from_cache, sender=Document)
Ejemplo n.º 7
0
    def test_go_live_page_will_be_published(self):
        # Connect a mock signal handler to page_published signal
        signal_fired = [False]
        signal_page = [None]

        def page_published_handler(sender, instance, **kwargs):
            signal_fired[0] = True
            signal_page[0] = instance

        page_published.connect(page_published_handler)

        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
            go_live_at=timezone.now() - timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(approved_go_live_at=timezone.now() -
                           timedelta(days=1))

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(p.live)
        self.assertTrue(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())

        management.call_command("publish_scheduled_pages")

        p = Page.objects.get(slug="hello-world")
        self.assertTrue(p.live)
        self.assertTrue(p.first_published_at)
        self.assertFalse(p.has_unpublished_changes)
        self.assertFalse(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())

        # Check that the page_published signal was fired
        self.assertTrue(signal_fired[0])
        self.assertEqual(signal_page[0], page)
        self.assertEqual(signal_page[0], signal_page[0].specific)
Ejemplo n.º 8
0
    def test_create_simplepage_post_publish(self):
        # Connect a mock signal handler to page_published signal
        mock_handler = mock.MagicMock()
        page_published.connect(mock_handler)

        # Post
        post_data = {
            'title': "New page!",
            'content': "Some content",
            'slug': 'hello-world',
            'action-publish': "Publish",
        }
        response = self.client.post(
            reverse('wagtailadmin_pages:add',
                    args=('tests', 'simplepage', self.root_page.id)),
            post_data)

        # Find the page and check it
        page = Page.objects.get(path__startswith=self.root_page.path,
                                slug='hello-world').specific

        # Should be redirected to explorer
        self.assertRedirects(
            response,
            reverse('wagtailadmin_explore', args=(self.root_page.id, )))

        self.assertEqual(page.title, post_data['title'])
        self.assertEqual(page.draft_title, post_data['title'])
        self.assertIsInstance(page, SimplePage)
        self.assertTrue(page.live)
        self.assertTrue(page.first_published_at)

        # Check that the page_published signal was fired
        self.assertEqual(mock_handler.call_count, 1)
        mock_call = mock_handler.mock_calls[0][2]

        self.assertEqual(mock_call['sender'], page.specific_class)
        self.assertEqual(mock_call['instance'], page)
        self.assertIsInstance(mock_call['instance'], page.specific_class)

        # treebeard should report no consistency problems with the tree
        self.assertFalse(any(Page.find_problems()),
                         'treebeard found consistency problems')
Ejemplo n.º 9
0
    def ready(self):
        user_model = get_user_model()
        post_save.connect(user_save_callback, sender=user_model)
        # Interesting situation: we use this pattern to account for
        # scrolling bugs in IE:
        # http://snipplr.com/view/518/
        # yet, url(null) trips up the ManifestStaticFilesStorage, so we
        # monkeypatch the regex so that url(null) is ignored

        storage.HashedFilesMixin.patterns = (("*.css", (
            r"""(url\((?!null)['"]{0,1}\s*(.*?)["']{0,1}\))""",
            (r"""(@import\s*["']\s*(.*?)["'])""", """@import url("%s")"""),
        )), )

        from v1.models.enforcement_action_page import EnforcementActionPage
        page_published.connect(break_enforcement_cache,
                               sender=EnforcementActionPage)
        page_unpublished.connect(break_enforcement_cache,
                                 sender=EnforcementActionPage)
        post_page_move.connect(break_enforcement_cache,
                               sender=EnforcementActionPage)
Ejemplo n.º 10
0
    def test_go_live_page_will_be_published(self):
        # Connect a mock signal handler to page_published signal
        signal_fired = [False]
        signal_page = [None]

        def page_published_handler(sender, instance, **kwargs):
            signal_fired[0] = True
            signal_page[0] = instance

        page_published.connect(page_published_handler)


        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
            go_live_at=timezone.now() - timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(approved_go_live_at=timezone.now() - timedelta(days=1))

        p = Page.objects.get(slug='hello-world')
        self.assertFalse(p.live)
        self.assertTrue(PageRevision.objects.filter(page=p).exclude(approved_go_live_at__isnull=True).exists())

        management.call_command('publish_scheduled_pages')

        p = Page.objects.get(slug='hello-world')
        self.assertTrue(p.live)
        self.assertTrue(p.first_published_at)
        self.assertFalse(p.has_unpublished_changes)
        self.assertFalse(PageRevision.objects.filter(page=p).exclude(approved_go_live_at__isnull=True).exists())

        # Check that the page_published signal was fired
        self.assertTrue(signal_fired[0])
        self.assertEqual(signal_page[0], page)
        self.assertEqual(signal_page[0], signal_page[0].specific)
Ejemplo n.º 11
0
 def subscribe(cls):
     page_published.connect(
         receiver=cls.populate,
         sender=cls.model,
         dispatch_uid=cls.model.__name__,
     )
     page_unpublished.connect(
         receiver=cls.delete,
         sender=cls.model,
         dispatch_uid=cls.model.__name__,
     )
     for model in cls.subscriptions:
         post_save.connect(
             receiver=cls.populate_many,
             sender=model,
             dispatch_uid=f'{cls.model.__name__}-{model.__name__}',
         )
         page_unpublished.connect(
             receiver=cls.populate_many,
             sender=model,
             dispatch_uid=f'{cls.model.__name__}-{model.__name__}',
         )
Ejemplo n.º 12
0
    def ready(self):
        from .handlers import general_published_handler, send_to_automate
        from .models import GeneralPage, TwoColumnGeneralPage

        page_published.connect(general_published_handler, sender=GeneralPage)
        page_published.connect(general_published_handler,
                               sender=TwoColumnGeneralPage)
        logger.info('general_published_handler should be connected now')

        # Send_to_automate deals with all publish events; not restricted to just home app models
        page_published.connect(send_to_automate)
Ejemplo n.º 13
0
from wagtail.core.signals import page_published, page_unpublished
from wagtail.contrib.frontend_cache.utils import purge_page_from_cache

from blog.models import BlogPost


def invalidate_frontend_cache_for_blog_index_page(sender, instance, **kwargs):
    """Invalidate the frontend cache for the parent BlogIndexPage of a
    BlogPost."""
    blog_post = instance
    # Recommended way to get parent page from
    # https://github.com/wagtail/wagtail/issues/2779#issuecomment-228472829
    blog_index_page = blog_post.get_parent()
    if blog_index_page:
        purge_page_from_cache(blog_index_page)


page_published.connect(invalidate_frontend_cache_for_blog_index_page,
                       sender=BlogPost)
page_unpublished.connect(invalidate_frontend_cache_for_blog_index_page,
                         sender=BlogPost)
Ejemplo n.º 14
0
    def ready(self):
        from .handlers import product_published_handler
        from .models import Product

        page_published.connect(product_published_handler, sender=Product)
        logger.info('product_published_handler should be connected now')
from django.core.management import call_command
from wagtail.core.signals import page_published, page_unpublished


def bake_site(sender, **kwargs):
    '''
    This helper function will trigger a re-build of the site automatically when
    a page is published or unpublished so that the static HTML being served
    gets synced with the changes published to the dynamic app.
    '''
    # TODO: either extend this function or call a different command so that we
    #       re-build and also re-deploy here.
    call_command('build')


page_published.connect(bake_site)
page_unpublished.connect(bake_site)
from wagtail.core import hooks
from wagtail.core.signals import page_published

from .indexer import index_page


@hooks.register("after_create_page")
def index_after_create_page(request, page):
    index_page(page)


@hooks.register("after_edit_page")
def index_after_edit_page(request, page):
    index_page(page)


def post_publish(sender, instance, **kwargs):
    index_page(instance)


page_published.connect(post_publish)
Ejemplo n.º 17
0
        try:
            page_files = {
                s3_obj["Key"]
                for s3_obj in page["Contents"]
                if splitext(s3_obj["Key"])[1] == '.html'
            }
            bucket_html_keys.update(page_files)
        except KeyError:
            continue

    # get diff of bucket keys vs uploaded s3 keys
    bucket_html_keys_2_remove = bucket_html_keys.difference(
        s3_html_keys_2_upload)

    # upload whats being uploaded
    for f in html_files_2_upload:
        s3_client.upload_file(
            Filename=f["Filename"],
            Bucket=settings.AWS_STORAGE_BUCKET_NAME_DEPLOYMENT,
            Key=f["Key"],
            ExtraArgs={'ContentType': 'text/html'})

    # remove whats being removed
    for key in bucket_html_keys_2_remove:
        s3_client.delete_object(
            Bucket=settings.AWS_STORAGE_BUCKET_NAME_DEPLOYMENT, Key=key)


page_published.connect(prerender_pages)
page_unpublished.connect(prerender_pages)
Ejemplo n.º 18
0
    def user_can_edit_obj(self, user, obj):
        return False

    def user_can_delete_obj(self, user, obj):
        return False


class NetlifyDeploymentAdmin(ModelAdmin):
    model = Deployment
    permission_helper_class = NetlifyPermissions
    menu_label = 'Netlify Deployments'
    menu_icon = 'collapse-up'
    menu_order = 1000
    list_display = ('deployment_created', 'deployment_time',
                    'deployment_created_by')
    form_fields_exclude = ('deployment_created_by', )


modeladmin_register(NetlifyDeploymentAdmin)


def trigger_deployment(**kwargs):
    if settings.NETLIFY_AUTO_DEPLOY is not False:
        revision = kwargs.get('revision')
        deployment = Deployment(deployment_created_by=revision.user)
        deployment.save()


page_published.connect(trigger_deployment)
page_unpublished.connect(trigger_deployment)
Ejemplo n.º 19
0
from django.db.models.signals import post_save
from django.dispatch import receiver

from wagtail.core.signals import page_published

from .functions import invalidate_cloudfront_caches
from .models import StickyNote, Footer, GiveToday


def clear_cloudfront_on_page_publish(sender, **kwargs):
    invalidate_cloudfront_caches()


page_published.connect(clear_cloudfront_on_page_publish)


# These functions clear caches on non-page models that drive content on the website
@receiver(post_save, sender=StickyNote)
def clear_cloudfront_on_sticky_save(sender, **kwargs):
    invalidate_cloudfront_caches()


@receiver(post_save, sender=Footer)
def clear_cloudfront_on_footer_save(sender, **kwargs):
    invalidate_cloudfront_caches()


@receiver(post_save, sender=GiveToday)
def clear_cloudfront_on_give_save(sender, **kwargs):
    invalidate_cloudfront_caches()
Ejemplo n.º 20
0
    # First check if app is in debug mode
    # and if we should perform sharing during
    # debug. Defaults to False
    share_in_debug = get_setting("SHARE_IN_DEBUG", required=False) or False

    if settings.DEBUG and not share_in_debug:
        return
    # Check if the sender is a subclass of 'SocialMediaSharablePageMixin'
    if not issubclass(sender, SocialMediaSharablePageMixin):
        # If the sender does not inherit the mixin, it should not be shared.
        return

    # Check if sender is a registered Wagtail Page
    if not sender in get_page_models():
        return

    # Get page instance
    instance = kwargs["instance"]

    # Check if page was already shared
    if instance.was_shared:
        return

    # Share the page
    share_page(instance)


# Register a receiver
page_published.connect(share_signal)
Ejemplo n.º 21
0
def register_signal_handlers():
    for model in get_page_models():
        page_published.connect(record_page_publish, sender=model)
Ejemplo n.º 22
0
    # I tryed to convert excerpt to markdown using tomd without success
    values = {
        "content":
        "Breaking news on OSR website !",
        "embeds": [{
            "title": instance.title,
            "url": "https://openstudyroom.org" + instance.url,
            "description": excerpt,
        }]
    }
    r = requests.post(discord_url, json=values)
    r.raise_for_status()


# Register two receivers
page_published.connect(send_to_discord, sender=EntryPage)
page_published.connect(send_to_discord, sender=StreamFieldEntryPage)


@receiver(post_save, sender=ForumPost)
def forum_post_to_discord(sender, instance, **kwargs):
    # don't announce edits
    instance.refresh_from_db()
    if instance.updates_count > 0:
        return
    # don't announce private admins forums forum.
    # This should be properly handled with a test if anonymous user can read forum.
    parent_id = instance.topic.forum.parent
    if parent_id is not None and parent_id.pk == 12:
        return
    if settings.DEBUG:
Ejemplo n.º 23
0
    def user_can_delete_obj(self, user, obj):
        return False


class NetlifyDeploymentAdmin(ModelAdmin):
    model = Deployment
    permission_helper_class = NetlifyPermissions
    menu_label = 'Netlify Deployments'
    menu_icon = 'collapse-up'
    menu_order = 1000
    list_display = ('deployment_created', 'deployment_time', 'deployment_created_by')
    form_fields_exclude = ('deployment_created_by',)


modeladmin_register(NetlifyDeploymentAdmin)


def trigger_deployment(**kwargs):
    if settings.NETLIFY_AUTO_DEPLOY:
        user = ''
        if kwargs.get('revision') is not None:
            user = kwargs.get('revision').user

        deployment = Deployment(deployment_created_by=user)
        deployment.save()


page_published.connect(trigger_deployment)
page_unpublished.connect(trigger_deployment)
def register_signal_handlers():
    page_published.connect(handle_publish,
                           dispatch_uid='wagtailbakery_page_published')
    page_unpublished.connect(handle_unpublish,
                             dispatch_uid='wagtailbakery_page_unpublished')
Ejemplo n.º 25
0
    content_panels = AbstractEmailForm.content_panels + [
        ImageChooserPanel('image'),
        StreamFieldPanel('body'),
        InlinePanel('form_fields', label="Form fields"),
        FieldPanel('thank_you_text', classname="full"),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email"),
    ]


def deploy_to_netlify_on_change(**kwargs):
    import requests
    from django.conf import settings
    try:
        netlify_deploy_hook_url = getattr(settings, 'NETLIFY_DEPLOY_HOOK_URL')
    except KeyError:
        return
    if not netlify_deploy_hook_url:
        return
    r = requests.post(netlify_deploy_hook_url)
    r.raise_for_status()


page_published.connect(deploy_to_netlify_on_change)
page_unpublished.connect(deploy_to_netlify_on_change)
Ejemplo n.º 26
0
from .signals import notify
from notifications.models import Notification


def notify_after_page_published(sender, instance, **kwargs):
    """
    In some cases, the page may not have any owner, for example the home page.
    For now we don't send any notification for these page as the logic behind finiding to who send
    a notification is not yet defined
    """
    if instance.owner:
        notify.send(instance, recipient=instance.owner, verb='published')


@receiver(post_save, sender=PageRevision)
def notify_after_revision_save(sender, instance, **kwargs):
    if not instance.submitted_for_moderation:
        return

    # Get list of publishers
    include_superusers = getattr(
        settings, 'WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS', True)
    recipients = users_with_page_permission(instance.page, 'publish',
                                            include_superusers)

    for recipient in recipients:
        notify.send(instance.page, recipient=recipient, verb='submitted')


page_published.connect(notify_after_page_published)
Ejemplo n.º 27
0
                    ,address=parent.address,type=event_type)
            parent.add_child(instance=child)
        else:
            child[0].title = title
            child[0].save()

    parent.save()
    #2. Go through all children - if slug does not match any of the provided dates delete it
    all_children = parent.get_children()
    all_slugs = set([instance.slug for instance in all_children])
    new_slugs = set(new_slugs)
    slugs_to_remove = RecurringEventChild.objects.filter(
        slug__in=all_slugs.difference(new_slugs))
    slugs_to_remove.delete()


def add_longitude_latitude(sender, **kwargs):
    obj = kwargs['instance']
    postcode_obj = Postcode.objects.filter(postcode=obj.postcode).first()
    if postcode_obj:
        obj.longitude = postcode_obj.longitude
        obj.latitude = postcode_obj.latitude
    obj.save()


# Register listeners for each page model class
page_published.connect(create_or_update_recurring_children,
                       sender=RecurringEventParent)
page_published.connect(add_longitude_latitude, sender=SingleDayEvent)
page_published.connect(add_longitude_latitude, sender=MultiDayEvent)
Ejemplo n.º 28
0
    parent_page_type = [
        "home.HomePage",
    ]


class MovieReview(BlogDetailPage):
    template = "blog/post.html"
    subpage_types = []
    parent_page_type = [
        "blog.BlogListingPage",
    ]

    movie = models.ForeignKey(
        "movies.Movie",
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
    )

    content_panels = Page.content_panels + [
        SnippetChooserPanel("author"),
        AutocompletePanel("movie"),
        StreamFieldPanel("content"),
    ]


# Send notifications for certain types of posts
page_published.connect(notify_subscribers, sender=BlogDetailPage)
page_published.connect(notify_subscribers, sender=VideoProjectPage)
page_published.connect(notify_subscribers, sender=MovieReview)
Ejemplo n.º 29
0
        return

    page = kwargs['instance']

    # First published check
    if page.first_published_at != page.last_published_at:
        return
    if page.get_parent().title not in ['Articles']:
        return

    webhook = Webhook.partial(settings.DISCORD_WEBHOOK_ID,
                              settings.DISCORD_WEBHOOK_TOKEN,
                              adapter=RequestsWebhookAdapter())
    embed = Embed(type="rich",
                  description='{}'.format(page.description),
                  colour=0x90E050)
    embed.set_author(name=page.title,
                     url='https://{}{}'.format(settings.SITE_NAME, page.url),
                     icon_url="https://i.imgur.com/9UsXLG0.png")
    if page.articlepage.feed_image:
        embed.set_thumbnail(url='https://{}{}'.format(
            settings.SITE_NAME,
            page.articlepage.feed_image.get_rendition('fill-800x600').url))
    embed.set_footer(text='{} | {}'.format(page.owner.username, (
        page.first_published_at).strftime('%A %d %B - %H:%M').title()))
    webhook.send(username='******', embed=embed)


# Register a receiver
page_published.connect(send_to_discord)
Ejemplo n.º 30
0
    menu_icon = 'doc-full'
    add_to_settings_menu = True


modeladmin_register(ArticleAdmin)


def _static_build_async(force=False,
                        pipeline=settings.STATIC_BUILD_PIPELINE,
                        **kwargs):
    """Calls each command in the static build pipeline in turn."""
    log_prefix = 'Static build task'
    for name, command in pipeline:
        if settings.DEBUG and not force:
            logger.info(f'{log_prefix} ‘{name}’ skipped.')
        else:
            logger.info(f'{log_prefix} ‘{name}’ started.')
            call_command(command)
            logger.info(f'{log_prefix} ‘{name}’ finished.')


def static_build(**kwargs):
    """Callback for Wagtail publish and unpublish signals."""
    # Spawn a process to do the actual build.
    process = Process(target=_static_build_async, kwargs=kwargs)
    process.start()


page_published.connect(static_build)
page_unpublished.connect(static_build)
Ejemplo n.º 31
0
    def ready(self):
        from .handlers import journal_published_handler
        from .models import JournalPage

        page_published.connect(journal_published_handler, sender=JournalPage)
        logger.info('journal_published_handler should be connected now')
Ejemplo n.º 32
0
def register_signal_handlers():
    page_published.connect(request_site_recrawl, sender=JobListingPage)
def register_signal_handlers():
    page_published.connect(
        handle_publish, dispatch_uid='wagtailbakery_page_published')
    page_unpublished.connect(
        handle_unpublish, dispatch_uid='wagtailbakery_page_unpublished')