def document_load_dynamic_elements(content_release, content, dynamic_element_keys):
    """ document_load_dynamic_elements """
    updated = False
    elements_to_remove = []

    for elt_list in dynamic_element_keys:
        item = get_from_dict(content, elt_list)

        try:
            model = apps.get_model(item['app'], item['class'])
            loaded_instance = model.objects.get(id=item['id'])
            item_serializer = loaded_instance.get_serializers()[item['serializer']]

            publisher_api = PublisherAPI()
            response = publisher_api.get_document_from_content_release(
                content_release.site_code,
                content_release.uuid,
                item_serializer['key'],
                item_serializer['type'],
            )

            if response['status'] == 'success':
                elt_list = elt_list[:-1]
                elt_list.append('data')
                set_in_dict(content, elt_list, json.loads(response['content'].document_json))
            else:
                raise Exception(response['error_msg'])
        except:
            elements_to_remove.append(elt_list[:-1])
    updated = True

    return content, updated
 def setUp(self):
     """ setUp """
     User = get_user_model()
     username = os.environ.get('CMS_SUPERUSER_USERNAME', 'superadmin')
     self.user = User.objects.get(username=username)
     self.page1 = TestPage.objects.get(id=3)
     self.page2 = TestPage.objects.get(id=4)
     self.page3 = TestPage.objects.get(id=5)
     self.content_release1 = WSSPContentRelease.objects.get(id=1)
     self.content_release2 = WSSPContentRelease.objects.get(id=2)
     self.content_release3 = WSSPContentRelease.objects.get(id=3)
     self.publisher_api = PublisherAPI(api_type='django')
     self.factory = RequestFactory()
     self.client = Client()
     self.client.force_login(self.user)
     self.page1.content_release = self.content_release1
     self.page1.save_revision(self.user)
     self.page2.content_release = self.content_release1
     self.page2.save_revision(self.user)
     self.page1.publish_to_release(self.page1.content_release,
                                   self.content_release1)
     self.publisher_api.set_live_content_release(
         self.content_release1.site_code, self.content_release1.uuid)
     self.publisher_api.get_live_content_release(
         self.content_release1.site_code)
     self.content_release1 = WSSPContentRelease.objects.get(id=1)
    def remove_from_release(self, instance=None, content_release=None):
        if not instance:
            instance = self

        publisher_api = PublisherAPI()

        serializers = instance.get_serializers()
        for key, serializer_item in serializers.items():
            paramaters = {
                'site_code': content_release.site_code,
                'release_uuid': content_release.uuid,
                'document_key': serializer_item['key'],
                'content_type': serializer_item['type'],
            }

            response = publisher_api.delete_document_from_content_release(**paramaters)
            if response['status'] != 'success':
                raise Exception(response['error_msg'])

            if serializer_item['type'] == 'page':
                logger.info('--- Adding remove_index to indexing queue %s' % (instance.specific.url_path))
                serialized_page = serializer_item['class'](instance=instance)
                data = serialized_page.data
                content_was_unpublished.send(sender=instance.__class__, site_id=content_release.site_code, release_id=content_release.uuid, page=instance, page_type=data['meta']['type'])

        return response
class WagtailSnapshotPublisherDynamicContentTests(TestCase):
    """ WagtailSnapshotPublisherDynamicContentTests """
    @classmethod
    def setUpTestData(cls):
        """ setUpTestData """
        call_command('load_test_data_fixtures', '--no-output')

    def setUp(self):
        """ setUp """
        User = get_user_model()
        username = os.environ.get('CMS_SUPERUSER_USERNAME', 'superadmin')
        self.user = User.objects.get(username=username)
        self.page1 = TestPage.objects.get(id=3)
        self.page2 = TestPage.objects.get(id=4)
        self.page3 = TestPage.objects.get(id=5)
        self.content_release1 = WSSPContentRelease.objects.get(id=1)
        self.content_release2 = WSSPContentRelease.objects.get(id=2)
        self.content_release3 = WSSPContentRelease.objects.get(id=3)
        self.publisher_api = PublisherAPI(api_type='django')
        self.factory = RequestFactory()
        self.client = Client()
        self.client.force_login(self.user)
        self.page1.content_release = self.content_release1
        self.page1.save_revision(self.user)
        self.page2.content_release = self.content_release1
        self.page2.save_revision(self.user)
        self.page1.publish_to_release(self.page1.content_release,
                                      self.content_release1)
        self.publisher_api.set_live_content_release(
            self.content_release1.site_code, self.content_release1.uuid)
        self.publisher_api.get_live_content_release(
            self.content_release1.site_code)
        self.content_release1 = WSSPContentRelease.objects.get(id=1)
def load_dynamic_element(sender, instance, *args, **kwargs):
    """ load_dynamic_element """
    if instance.is_stage:
        publisher_api = PublisherAPI()

        # get all ReleaseContent with dynamic element
        release_documents = instance.release_documents.filter(
            parameters__key='have_dynamic_elements',
            parameters__content='True',
            content_type='page',
        )

        for release_document in release_documents:
            response_extra = publisher_api.get_document_extra_from_content_release(
                instance.site_code,
                instance.uuid,
                release_document.document_key,
                release_document.content_type,
            )
            if response_extra['status'] == 'success' and not release_document.deleted:
                data = json.loads(release_document.document_json)
                dynamic_element_keys = json.loads(response_extra['content'].get(key='dynamic_element_keys').content)
                data, updated = document_load_dynamic_elements(instance, data, dynamic_element_keys)
                if updated:
                    release_document.document_json = json.dumps(data)
                    release_document.save()
 def handle(self, *args, **options):
     """ handle """
     site_codes = ContentRelease.objects.values_list('site_code',
                                                     flat=True).distinct()
     for site_code in site_codes:
         publisher_api = PublisherAPI(api_type='django')
         publisher_api.get_live_content_release(site_code)
def release_archive(request, release_id):
    """ release_archive """
    publisher_api = PublisherAPI()
    release = WSSPContentRelease.objects.get(id=release_id)
    response = publisher_api.archive_content_release(release.site_code, release.uuid)
    if response['status'] != 'success':
        raise Http404(response['error_msg'])
    return redirect(absolute_path(request, 'wagtailsnapshotpublisher', 'wsspcontentrelease'))
    def clean(self):
        """ clean """
        super().clean()

        # get live release
        if self.publish_to_live_release:
            self.publish_to_live_release = False
            publisher_api = PublisherAPI()
            response = publisher_api.get_live_content_release(self.site_code)
            if response['status'] == 'error':
                raise ValidationError({'site_code': response['error_msg']})

            self.content_release = WSSPContentRelease.objects.get(id=response['content'].id)
    def remove_from_content_release(self, content_release, recursively=False):
        """ unpublish_from_content_release """
        results = []
        errors = 0
        publisher_api = PublisherAPI()

        # Build list of pages to remove.
        pages_to_remove = [self]
        if recursively:
            pages_to_remove.extend(self.get_child_pages_recursively())

        logger.info('There are %d pages to remove' % (len(pages_to_remove)))

        # Remove the pages from the release.
        for page in pages_to_remove:
            try:
                # Remove page by adding tombstone release document.
                page = page.specific
                logger.info('Removing %s' % (page))
                page.remove_from_release(None, content_release)
                results.append({ 'code': 0, 'page_name': page.title, 'full_path': page.url_path })

            except Exception as e:
                errors = errors + 1
                logger.error('Failed to remove page %s, %s' % (page, e))
                results.append({ 'code': 1, 'page_name': page.title, 'full_path': page.url_path, 'message': e })

        return { 'code': 0, 'total_count': len(pages_to_remove), 'error_count': errors, 'results': results }
    def publish_to_release(self, instance=None, content_release=None, extra_parameters={}):
        """ publish_to_release """
        if not instance:
            instance = self

        if not content_release:
            content_release = self.content_release

        serializers = instance.get_serializers()

        for key, serializer_item in serializers.items():
            have_dynamic_elements = False
            serialized_page = serializer_item['class'](instance=instance)
            data = serialized_page.data
            if serializer_item['type'] == 'page':
                data['meta']['full_path'] = serializer_item['key']
            dynamic_element_keys = get_dynamic_element_keys(data)
            if dynamic_element_keys:
                extra_parameters.update({
                    'dynamic_element_keys': json.dumps(dynamic_element_keys),
                })
                have_dynamic_elements = True

            extra_parameters.update({
                'have_dynamic_elements': have_dynamic_elements,
            })

            publisher_api = PublisherAPI()
            json_data = json.dumps(data)
            response = publisher_api.publish_document_to_content_release(
                content_release.site_code,
                content_release.uuid,
                json_data,
                serializer_item['key'],
                serializer_item['type'],
                extra_parameters,
            )

            logger.info('--- Published %s to content release %s' % (instance, response['status']))

            if response['status'] == 'success':
                if serializer_item['type'] == 'page':
                    data['full_path'] = serializer_item['key']
                    logger.info('--- Adding to indexing queue %s' % (data['full_path']))
                    content_was_published.send(sender=self.__class__, site_id=content_release.site_code, release_id=content_release.uuid, title=data.get("title"), content=data, page=self)
            else:
                raise Exception(response['error_msg'])
def remove_page_and_children(request, page_id=None):
    page = Page.objects.get(id=page_id).specific

    if request.method == 'GET':
        site_code = page.site_code

        publisher_api = PublisherAPI()
        rsp = publisher_api.list_content_releases(site_code, status='0', after=None) # Fetch preview releases ('0' will be cast to an integer)
        if rsp['status'] == 'success':
            releases = rsp['content']
        else:
            releases = []

        details = {
            'page': page,
            'releases': releases,
        }

        return render(request, 'wagtailadmin/remove/detail.html', details)

    if request.method == 'POST':
        release_uuid = request.POST.get('release_uuid')
        publish_current = request.POST.get('publish_current')

        release = WSSPContentRelease.objects.get(uuid=release_uuid)
        rsp = page.remove_from_release_with_id(release.id)
        if rsp['code'] == 0:
            error = None
            results = rsp['results']
            total_count = rsp['total_count']
            error_count = rsp['error_count']
        else:
            error = 'Failed to un-publish page: %s' % (rsp['message'])
            results = []
            total_count = None
            error_count = None

        details = {
            'page': page,
            'results': results,
            'results_total': total_count,
            'results_errors': error_count,
            'error': error,
        }

        return render(request, 'wagtailadmin/remove/results.html', details)
def release_unset_stage(request, release_id):
    publisher_api = PublisherAPI()
    release = WSSPContentRelease.objects.get(id=release_id)
    response = None

    # save publisher user in release
    if request:
        release.publisher = request.user
        release.save()

    logger.info('Setting release %s stage immediately', release.uuid)
    response = publisher_api.unset_stage_content_release(release.site_code, release.uuid)

    if response['status'] != 'success':
        raise Http404(response['error_msg'])

    return redirect(absolute_path(request, 'wagtailsnapshotpublisher', 'wsspcontentrelease'))
def release_set_stage(request, release_id, publish_datetime=None, set_stage_button=False):
    """ release_set_stage """
    if not publish_datetime:
        if request and request.POST:
            form = PublishReleaseForm(request.POST)
            if form.is_valid():
                if form.cleaned_data['publish_type'] == 'now':
                    # Will publish immediately.
                    publish_datetime = None
                else:
                    publish_datetime = form.cleaned_data['publish_datetime']
            else:
                logger.debug('Set stage form is invalid')

    publisher_api = PublisherAPI()
    release = WSSPContentRelease.objects.get(id=release_id)
    response = None

    # save publisher user in release
    if request:
        release.publisher = request.user
        release.save()

    if publish_datetime:
        logger.info('Setting release %s stage at %s', release.uuid, publish_datetime)
        response = publisher_api.freeze_content_release(release.site_code, release.uuid,
                                                        publish_datetime)
    else:
        logger.info('Setting release %s stage immediately', release.uuid)
        response = publisher_api.set_stage_content_release(release.site_code, release.uuid)

    if response['status'] != 'success':
        raise Http404(response['error_msg'])

    # Send release_was_staged signal.
    release_was_staged.send(sender=release.__class__, release=release)

    WSSPContentRelease.objects.stage(
        site_code=release.site_code,
    )
    return redirect(absolute_path(request, 'wagtailsnapshotpublisher', 'wsspcontentrelease'))
 def test_set_stage(self):
     """ unittest when content release go live """
     publisher_api = PublisherAPI(api_type='django')
     response = publisher_api.add_content_release('site1', 'title1', '0.1')
     content_release = response['content']
     document_json = json.dumps({'page_title': 'Test'})
     response = publisher_api.publish_document_to_content_release(
         'site1',
         content_release.uuid,
         document_json,
         'key1',
     )
     publisher_api.set_stage_content_release('site1', content_release.uuid)
     publisher_api.get_stage_content_release('site1')
Exemple #15
0
 def setUp(self):
     """ setUp """
     User = get_user_model()
     username = os.environ.get('CMS_SUPERUSER_USERNAME', 'superadmin')
     self.user = User.objects.get(username=username)
     self.page1 = TestPage.objects.get(id=3)
     self.page2 = TestPage.objects.get(id=4)
     self.test_model = TestModel.objects.get(id=1)
     self.content_release = WSSPContentRelease.objects.get(id=1)
     self.publisher_api = PublisherAPI(api_type='django')
     self.factory = RequestFactory()
     self.client = Client()
     self.client.force_login(self.user)
     self.url_release_admin_index = ReleaseAdmin().url_helper.index_url
def get_releases(request, site_code):
    """ get_releases """
    # time_now = timezone.now()
    # logger.info('Getting releases for site code %s after %s', site_code, time_now.strftime(DATETIME_FORMAT))
    # response = list_live_and_upcoming_content_releases(site_code, 1, time_now) # Status FROZEN = 1

    # if response['status'] == 'success':
    #     releases = list(response['content'].values('uuid', 'title', 'publish_datetime', 'is_live'))
    #     logger.info('Releases are %s', releases)
    # else:
    #     return response

    live_release = None
    stage_release = None
    publisher_api = PublisherAPI()

    response = publisher_api.get_live_content_release(site_code)
    if response['status'] == 'success':
        live_release = {
            'uuid': response['content'].uuid,
            'title': response['content'].title,
            'publish_datetime': response['content'].publish_datetime,
        }

    response = publisher_api.get_stage_content_release(site_code)
    if response['status'] == 'success':
        stage_release = {
            'uuid': response['content'].uuid,
            'title': response['content'].title,
            'publish_datetime': response['content'].publish_datetime,
        }

    return JsonResponse({
        'stage': stage_release,
        'live': live_release,
    }, safe=False)
    def republish_to_content_release(self, content_release, publish_all=False, recursively=True):
        """ republish_to_content_release """

        results = []
        errors = 0
        publisher_api = PublisherAPI()

        # Build list of pages to re-publish.
        pages_to_republish = [self]
        if recursively:
            pages_to_republish.extend(self.get_child_pages_recursively())

        logger.info('There are %d pages to re-publish' % (len(pages_to_republish)))

        # Build list of pages already published to the release.
        already_published = {}
        release_documents = ReleaseDocument.objects.filter(content_releases=content_release.id, content_type='page')
        for release_document in release_documents:
            logger.info('Release doc is %s' % (release_document))
            already_published[release_document.document_key] = True

        # Re-publish the pages.
        for page in pages_to_republish:
            try:
                # Publish page.
                page = page.specific
                revision = page.get_latest_revision()
                if publish_all or already_published.get(page.url_path):
                    logger.info('Re-publishing %s (revision %s)' % (page, revision.id))
                    page.publish_to_release(None, content_release, { 'revision_id': revision.id })
                    results.append({ 'code': 0, 'page_name': page.title, 'full_path': page.url_path })
                else:
                    logger.info('%s is not currently published' % (page.url_path))
                    results.append({ 'code': 2, 'page_name': page.title, 'full_path': page.url_path })

            except Exception as e:
                errors = errors + 1
                logger.error('Failed to re-publish page %s, %s' % (page, e))
                results.append({ 'code': 1, 'page_name': page.title, 'full_path': page.url_path, 'message': e })

        return { 'code': 0, 'total_count': len(pages_to_republish), 'error_count': errors, 'results': results }
    def unpublish_from_content_release(self, content_release, recursively=False):
        """ unpublish_from_content_release """
        results = []
        errors = 0
        publisher_api = PublisherAPI()

        # Build list of pages to unpublish.
        pages_to_unpublish = [self]
        if recursively:
            pages_to_unpublish.extend(self.get_child_pages_recursively())

        logger.info('There are %d pages to un-publish' % (len(pages_to_unpublish)))

        # Build list of pages already published to the release.
        already_published = {}
        release_documents = ReleaseDocument.objects.filter(content_releases=content_release.id, content_type='page')
        for release_document in release_documents:
            logger.info('Release doc is %s' % (release_document))
            already_published[release_document.document_key] = True

        # Unpublish the pages from the release.
        for page in pages_to_unpublish:
            try:
                # Unpublish page.
                page = page.specific
                logger.info('already_published[%s] is %s' % (page.url_path, already_published.get(page.url_path)))
                if already_published.get(page.url_path):
                    logger.info('Un-publishing %s' % (page))
                    page.unpublish_from_release(None, content_release)
                    results.append({ 'code': 0, 'page_name': page.title, 'full_path': page.url_path })
                else:
                    results.append({ 'code': 2, 'page_name': page.title, 'full_path': page.url_path })

            except Exception as e:
                errors = errors + 1
                logger.error('Failed to un-publish page %s, %s' % (page, e))
                results.append({ 'code': 1, 'page_name': page.title, 'full_path': page.url_path, 'message': e })

        return { 'code': 0, 'total_count': len(pages_to_unpublish), 'error_count': errors, 'results': results }
def get_content_details(site_code, release_uuid, content_type, content_key):
    """ get_content_details """
    publisher_api = PublisherAPI()

    content_release = None

    try:
        if release_uuid:
            # get ContentRelease
            content_release = WSSPContentRelease.objects.get(
                site_code=site_code,
                uuid=release_uuid,
            )
        else:
            # get live ContentRelease
            response = publisher_api.get_live_content_release(site_code)
            if response['status'] == 'error':
                return response
            else:
                release = response['content']
                content_release = WSSPContentRelease.objects.get(id=release.id)
                release_uuid = content_release.uuid
    except WSSPContentRelease.DoesNotExist:
        pass

    # Fetch document from the content release.
    response = publisher_api.get_document_from_content_release(
        site_code,
        release_uuid,
        content_key,
        content_type,
    )

    base_content_release = None
    if response['status'] == 'error' and response['error_code'] == 'release_document_does_not_exist':
        # Release doc not found, try in the base release for preview releases.
        if content_release.status == 0:
            if content_release.use_current_live_as_base_release:
                response = publisher_api.get_live_content_release(site_code)
                if response['status'] == 'success':
                    release = response['content']
                    base_content_release = WSSPContentRelease.objects.get(id=release.id)
            else:
                base_content_release = content_release.base_release

    if base_content_release != None:
        # Fetch document from the base content release if available (should only happen for preview releases).
        response = publisher_api.get_document_from_content_release(
            site_code,
            base_content_release.uuid,
            content_key,
            content_type,
        )

    if response['status'] == 'success':
        data = json.loads(response['content'].document_json)

        response_extra = publisher_api.get_document_extra_from_content_release(
            site_code,
            release_uuid,
            content_key,
            content_type,
        )
        if response_extra['status'] == 'success':
            try:
                dynamic_element_keys = json.loads(response_extra['content'].get(key='dynamic_element_keys').content)
                data, updated = document_load_dynamic_elements(content_release, data, dynamic_element_keys)
            except:
                pass
    else:
        return response

    return data
    def test_copy_release(self):
        """ unittest copy ContentRelease """

        # create release
        publisher_api = PublisherAPI(api_type='django')
        response = publisher_api.add_content_release('site1', 'title1', '0.1',
                                                     {
                                                         'p1': 'test1',
                                                         'p2': 'test2',
                                                     })
        content_release = response['content']

        # add 2 documents to te release
        document_json = json.dumps({'page_title': 'Test1'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release.uuid,
            document_json,
            'key1',
        )
        document_json = json.dumps({'page_title': 'Test2'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release.uuid,
            document_json,
            'key2',
        )

        # copy release
        new_content_release = content_release.copy({'version': '0.2'})

        self.assertNotEqual(content_release.version,
                            new_content_release.version)
        self.assertEqual(new_content_release.version, '0.2')
        content_release_values = ContentRelease.objects.values_list(
            'title',
            'site_code',
            'status',
            'publish_datetime',
            'use_current_live_as_base_release',
            'base_release',
            'is_live',
        )
        self.assertEqual(
            content_release_values.get(id=content_release.id),
            content_release_values.get(id=new_content_release.id),
        )

        # compare release_documents
        release_documents = content_release.release_documents.order_by(
            'id').values('id')
        new_release_documents = new_content_release.release_documents.order_by(
            'id').values('id')
        self.assertEqual(list(release_documents), list(new_release_documents))

        # compare extra_parameters
        extra_parameters = ContentReleaseExtraParameter.objects.filter(
            content_release=content_release, ).order_by('key').values(
                'key',
                'content',
            )
        new_extra_parameters = ContentReleaseExtraParameter.objects.filter(
            content_release=content_release, ).order_by('key').values(
                'key',
                'content',
            )
        self.assertEqual(list(extra_parameters), list(new_extra_parameters))
    def test_set_live(self):
        """ unittest when content release go live """
        publisher_api = PublisherAPI(api_type='django')
        response = publisher_api.add_content_release('site1', 'title1', '0.1')
        content_release = response['content']
        document_json = json.dumps({'page_title': 'Test'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release.uuid,
            document_json,
            'key1',
        )
        # set stage
        publisher_api.set_stage_content_release('site1', content_release.uuid)
        publisher_api.get_stage_content_release('site1')
        # set live
        publisher_api.set_live_content_release('site1', content_release.uuid)
        publisher_api.get_live_content_release('site1')

        # set live, not base release
        response = publisher_api.add_content_release('site1', 'title2', '0.2')
        content_release2 = response['content']
        document_json2 = json.dumps({'page_title': 'Test2'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release2.uuid,
            document_json2,
            'key1',
        )
        document_json3 = json.dumps({'page_title': 'Test3'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release2.uuid,
            document_json3,
            'key2',
        )
        publisher_api.set_stage_content_release('site1', content_release2.uuid)
        publisher_api.get_stage_content_release('site1')
        publisher_api.set_live_content_release('site1', content_release2.uuid)
        publisher_api.get_live_content_release('site1')
        content_release2 = ContentRelease.objects.get(
            uuid=content_release2.uuid)
        self.assertEqual(content_release2.release_documents.count(), 2)
        release_document1 = content_release2.release_documents.get(
            document_key='key1', )
        release_document2 = content_release2.release_documents.get(
            document_key='key2', )
        self.assertEqual(json.loads(release_document1.document_json),
                         {'page_title': 'Test2'})
        self.assertEqual(json.loads(release_document2.document_json),
                         {'page_title': 'Test3'})

        # copy base release documents
        response = publisher_api.add_content_release('site1', 'title3', '0.3',
                                                     None,
                                                     content_release2.uuid)
        content_release3 = response['content']
        document_json4 = json.dumps({'page_title': 'Test4'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release3.uuid,
            document_json4,
            'key2',
        )
        publisher_api.set_stage_content_release('site1', content_release3.uuid)
        publisher_api.set_live_content_release('site1', content_release3.uuid)

        # publish to content release and get the last one and check in the copy works
        response = publisher_api.add_content_release('site1', 'title4', '0.4',
                                                     None, None, True)
        content_release4 = response['content']
        document_json5 = json.dumps({'page_title': 'Test5'})
        response = publisher_api.publish_document_to_content_release(
            'site1',
            content_release4.uuid,
            document_json5,
            'key1',
        )
        publisher_api.set_stage_content_release('site1', content_release4.uuid)
        publisher_api.get_stage_content_release('site1')
        publisher_api.set_live_content_release('site1', content_release4.uuid)
        publisher_api.get_live_content_release('site1')
        content_release3 = ContentRelease.objects.get(
            uuid=content_release3.uuid)
        self.assertEqual(content_release3.release_documents.count(), 2)
        release_document1 = content_release3.release_documents.get(
            document_key='key1', )
        release_document2 = content_release3.release_documents.get(
            document_key='key2', )
        self.assertEqual(json.loads(release_document1.document_json),
                         {'page_title': 'Test2'})
        self.assertEqual(json.loads(release_document2.document_json),
                         {'page_title': 'Test4'})

        content_release4 = ContentRelease.objects.get(
            uuid=content_release4.uuid)
        self.assertEqual(content_release4.release_documents.count(), 2)
        release_document1 = content_release4.release_documents.get(
            document_key='key1', )
        release_document2 = content_release4.release_documents.get(
            document_key='key2', )
        self.assertEqual(json.loads(release_document1.document_json),
                         {'page_title': 'Test5'})
        self.assertEqual(json.loads(release_document2.document_json),
                         {'page_title': 'Test4'})

        self.assertEqual(ContentRelease.objects.archived('site1').count(), 3)
    def copy_document_release_ref_from_baserelease(self):
        """ get parent release """
        if self.use_current_live_as_base_release:
            self.base_release = self.__class__.objects.filter(
                publish_datetime__lt=self.publish_datetime, site_code=self.site_code).order_by(
                    '-publish_datetime').first()

        if self.base_release:
            publisher_api = PublisherAPI()
            dynamic_documents = self.base_release.release_documents.filter(
                parameters__key='have_dynamic_elements',
                parameters__content='True',
            )

            for dynamic_document in dynamic_documents:
                dynamic_element_keys = None
                try:
                    self.release_documents.get(
                        document_key=dynamic_document.document_key,
                        content_type=dynamic_document.content_type,
                    )
                except ReleaseDocument.DoesNotExist:
                    add_document_to_release = False
                    dynamic_element_keys = json.loads(dynamic_document.parameters.get(key='dynamic_element_keys').content)
                    content = json.loads(dynamic_document.document_json)

                    for elt_list in dynamic_element_keys:
                        item = get_from_dict(content, elt_list)
                    
                        elements_to_remove = []

                        # try:
                        model = apps.get_model(item['app'], item['class'])
                        loaded_instance = model.objects.get(id=item['id'])
                        item_serializer = loaded_instance.get_serializers()[item['serializer']]

                        if self.release_documents.filter(document_key=item_serializer['key'], content_type=item_serializer['type']).exists():
                            add_document_to_release = True
                            break

                    # load dynamic content
                    data, updated = document_load_dynamic_elements(self, json.loads(dynamic_document.document_json), dynamic_element_keys)
 
                    # get extra paramaters
                    parameters = None
                    response = publisher_api.get_document_extra_from_content_release(
                        self.site_code,
                        self.base_release.uuid,
                        dynamic_document.document_key,
                        dynamic_document.content_type,
                    )
                    if response['status'] == 'success':
                        parameters = {parameter.key: parameter.content for parameter in response['content']}

                    # add content to release
                    publisher_api.publish_document_to_content_release(
                        self.site_code,
                        self.uuid,
                        json.dumps(data),
                        dynamic_document.document_key,
                        dynamic_document.content_type,
                        parameters=parameters,
                    )                    

        super(WSSPContentRelease, self).copy_document_release_ref_from_baserelease()
def compare_release(request, release_id, release_id_to_compare_to=None, set_live_button=False, set_stage_button=False):
    """ compare_release """
    publisher_api = PublisherAPI()
    release = WSSPContentRelease.objects.get(id=release_id)

    publish_release_form = PublishReleaseForm()
    frozen_releases_form = FrozenReleasesForm(release.site_code)

    if request.method == 'POST' and release_id_to_compare_to is None:
        frozen_releases_form = FrozenReleasesForm(release.site_code, request.POST)
        if frozen_releases_form.is_valid():
            # redirect to compare with this release
            release_id_to_compare_to = frozen_releases_form.cleaned_data['releases']
            return release_detail(request, release_id, set_live_button, set_stage_button, release_id_to_compare_to.id)

    if request.method == 'POST' and release_id_to_compare_to is None:
        publish_release_form = PublishReleaseForm(request.POST)
        if publish_release_form.is_valid():
            publish_datetime = publish_release_form.cleaned_data['publish_datetime']

            if publish_datetime:
                publish_datetime = publish_datetime.strftime('%Y-%m-%dT%H:%M:%S%z')

            return release_set_live(request, release_id, publish_datetime)


    if frozen_releases_form.fields['releases'].queryset is None or \
            not frozen_releases_form.fields['releases'].queryset.exists():
        frozen_releases_form = None

    # get current live release
    compare_with_live = True
    response = publisher_api.get_live_content_release(release.site_code)
    if response['status'] == 'error':
        return {
            'release': release,
            'error_msg': response['error_msg'],
            'publish_release_form': publish_release_form,
        }

    release_to_compare_to = response['content']
    if release_id_to_compare_to and release_to_compare_to.id != release_id_to_compare_to:
        compare_with_live = False
        release_to_compare_to = WSSPContentRelease.objects.get(id=release_id_to_compare_to)
    else:
        release_to_compare_to = WSSPContentRelease.objects.get(id=release_to_compare_to.id)

    response = publisher_api.compare_content_releases(release.site_code, release.uuid,
                                                      release_to_compare_to.uuid)
    comparison = response['content']

    added_pages = []
    removed_pages = []
    changed_pages = []
    extra_contents = []
    for item  in comparison:
        if item['content_type'] == 'page':
            try:
                if item['diff'] == 'Added':
                    try:
                        page_revision = PageRevision.objects.get(id=item['parameters']['revision_id'])
                    except:
                        logger.info('Page has been deleted from Wagtail: %s' % (item))
                        item['deleted_in_wagtail'] = True
                    item['page_revision'] = page_revision
                    item['title'] = json.loads(page_revision.content_json)['title']
                    added_pages.append(item)
                if item['diff'] == 'Removed':
                    try:
                        page_revision = PageRevision.objects.get(id=item['parameters']['revision_id'])
                    except:
                        logger.info('Page has been deleted from Wagtail: %s' % (item))
                        item['deleted_in_wagtail'] = True
                    item['title'] = json.loads(page_revision.content_json)['title']
                    item['page_revision'] = page_revision
                    removed_pages.append(item)
                if item['diff'] == 'Changed' and 'revision_id' in item['parameters']['release_from']:
                    try:
                        page_revision = PageRevision.objects.get(id=item['parameters']['release_from']['revision_id'])
                    except:
                        logger.info('Page has been deleted from Wagtail: %s' % (item))
                        item['deleted_in_wagtail'] = True
                    item['page_revision_from'] = page_revision
                    item['page_revision_compare_to'] = PageRevision.objects.get(
                        id=item['parameters']['release_compare_to']['revision_id'])
                    item['title'] = json.loads(page_revision.content_json)['title']
                    changed_pages.append(item)
            except Exception as e:
                logger.info('Error while comparing item: %s' % (item))
        else:
            extra_contents.append(item)

    return {
        'comparison': comparison,
        'added_pages': added_pages,
        'changed_pages': changed_pages,
        'removed_pages': removed_pages,
        'extra_contents': json.dumps(extra_contents, indent=4) if extra_contents and \
            request.user.has_perm('wagtailadmin.access_dev') else None,
        'release': release,
        'release_to_compare_to': release_to_compare_to,
        'publish_release_form': publish_release_form,
        'frozen_releases_form': frozen_releases_form,
        'compare_with_live': compare_with_live,
    }