Skip to content

Commit

Permalink
#128 - Implemented validation of the content to be shared
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] authored and hvelarde committed Sep 11, 2017
1 parent afba2ae commit a80fe1b
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 0 deletions.
28 changes: 28 additions & 0 deletions sc/social/like/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@
handler=".subscribers.assign_canonical_url"
/>

<subscriber
zcml:condition="installed plone.app.dexterity"
for="plone.dexterity.interfaces.IDexterityContent
Products.DCWorkflow.interfaces.IAfterTransitionEvent"
handler=".subscribers.social_content_check"
/>

<subscriber
zcml:condition="installed plone.app.dexterity"
for="plone.dexterity.interfaces.IDexterityContent
plone.dexterity.interfaces.IEditFinishedEvent"
handler=".subscribers.social_content_check"
/>

<subscriber
zcml:condition="installed Products.ATContentTypes"
for="Products.ATContentTypes.interfaces.IATContentType
Products.DCWorkflow.interfaces.IAfterTransitionEvent"
handler=".subscribers.social_content_check"
/>

<subscriber
zcml:condition="installed Products.ATContentTypes"
for="Products.ATContentTypes.interfaces.IATContentType
Products.Archetypes.interfaces.IObjectEditedEvent"
handler=".subscribers.social_content_check"
/>

<include file="behaviors.zcml" />

</configure>
46 changes: 46 additions & 0 deletions sc/social/like/subscribers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
"""
from plone import api
from plone.registry.interfaces import IRegistry
from Products.CMFCore.WorkflowCore import WorkflowException
from sc.social.like.config import IS_PLONE_5
from sc.social.like.config import PROJECTNAME
from sc.social.like.interfaces import ISocialLikeSettings
from sc.social.like.logger import logger
from utils import get_content_image
from utils import validate_description_social
from utils import validate_image_social
from utils import validate_title_social
from zope.component import getUtility
from zope.schema.interfaces import WrongType

Expand Down Expand Up @@ -107,3 +112,44 @@ def assign_canonical_url(obj, event):
'Canonical domain not set in Social Media configlet; '
"Facebook's Open Graph canonical URL (og:orl) will not be available"
)


def social_content_check(obj, event):

request = obj.REQUEST
verify_state = 'published'

if getattr(event, 'status', None):
state = event.status['review_state']
else:
try:
state = api.content.get_state(obj)
except WorkflowException:
state = ''
verify_state = ''

if obj.restrictedTraverse('@@social_likes_view').enabled \
and state == verify_state:

title = getattr(obj, 'title', None)
v_title = validate_title_social(title)
if title and v_title:
msg = v_title
api.portal.show_message(message=msg, request=request, type='warning')

try:
description = obj.Description()
v_description = validate_description_social(description)
if description and v_description:
msg = v_description
api.portal.show_message(message=msg, request=request, type='warning')
except AttributeError:
pass

image = get_content_image(obj)
if image:
v_image = validate_image_social(image)
if v_image:
msg = v_image
logger.info(msg)
api.portal.show_message(message=msg, request=request, type='warning')
Binary file added sc/social/like/tests/images/imgtest_1024x768.bmp
Binary file not shown.
Binary file added sc/social/like/tests/images/imgtest_200x200.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions sc/social/like/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
# -*- coding: utf-8 -*-
from plone import api
from sc.social.like.testing import INTEGRATION_TESTING
from sc.social.like.testing import load_image
from sc.social.like.tests.api_hacks import set_image_field
from sc.social.like.utils import get_content_image
from sc.social.like.utils import validate_canonical_domain
from sc.social.like.utils import validate_description_social
from sc.social.like.utils import validate_image_social
from sc.social.like.utils import validate_title_social
from zope.interface import Invalid

import unittest


class UtilsTestCase(unittest.TestCase):

layer = INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']

with api.env.adopt_roles(['Manager']):
self.obj = api.content.create(
self.portal, type='News Item', id='foo')
set_image_field(self.obj, load_image(1024, 768), 'image/png')

self.obj2 = api.content.create(
self.portal, type='News Item', id='foo2')
set_image_field(self.obj2, load_image(200, 200), 'image/png')

self.obj3 = api.content.create(
self.portal, type='News Item', id='foo3')
set_image_field(self.obj3, load_image(200, 200), 'image/bmp')

def test_validate_canonical_domain_valid(self):
self.assertTrue(validate_canonical_domain('http://example.org'))
self.assertTrue(validate_canonical_domain('https://example.org'))
Expand All @@ -20,3 +47,33 @@ def test_validate_canonical_domain_invalid(self):
validate_canonical_domain('https://example.org?foo') # query
with self.assertRaises(Invalid):
validate_canonical_domain('https://example.org#bar') # fragment

def test_validate_title_social_valid(self):
self.assertFalse(validate_title_social('Lorem ipsum dolor sit amet, '
'consectetur adipiscing elit.'))

def test_validate_title_social_invalid(self):
self.assertTrue(validate_title_social('Integer molestie massa auctor diam '
'volutpat, et sodales lectus pulvinar.'))

def test_validate_description_social_valid(self):
self.assertFalse(validate_title_social('Lorem ipsum dolor sit amet, '
'consectetur adipiscing elit.'))

def test_validate_description_social_invalid(self):
self.assertTrue(validate_description_social('Integer molestie massa auctor diam '
'volutpat, et sodales lectus pulvinar.'))

self.assertTrue(validate_description_social('Sed pellentesque quam tincidunt neque imperdiet porta. '
'Fusce nec vestibulum felis, ut faucibus odio. Maecenas sit '
'amet dapibus diam.'))

def test_validate_image_social_valid(self):
image = get_content_image(self.obj)
self.assertFalse(validate_image_social(image))

def test_validate_image_social_invalid(self):
image = get_content_image(self.obj2)
self.assertTrue(validate_image_social(image))
image = get_content_image(self.obj3)
self.assertTrue(validate_image_social(image))
62 changes: 62 additions & 0 deletions sc/social/like/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,65 @@ def get_valid_objects(brains):
logger.warn(msg.format(b.getPath()))
continue
yield obj


def validate_title_social(value):
"""Check if title field have more than 70 characters."""
if len(value) > 70:
msg = u'Title have more than 70 characters.'
logger.info(msg)
return msg
return


def validate_description_social(value):
"""Check if description field have more than 200 characters."""

if value and len(value) > 200:
msg = u'Description have more than 200 characters.'
logger.info(msg)
return msg

elif value and (value.count('.') < 2 or value.count('.') > 2):
msg = u'Description should contain at least 2 phrases.'
logger.info(msg)
return msg

return


def validate_image_social(value):
"""Check if image be in formats mime type, dimensions and size."""

list_mimetypes = ['image/jpeg', 'image/png', 'image/gif', ' image/webp']

type = getattr(value, 'mimetype', None)
if type not in list_mimetypes:
msg = u'Image mime type not supported: {0}'
logger.info(msg.format(type))
return msg.format(type)

size = value.size
if size > 5242880:
msg = u'Image size should be less than 5MB.'
logger.info(msg)
return msg

width, height = (value.width, value.height)
if width < 600 and height < 315:
msg = u'Image dimensions should be at least 600 x 315.'
logger.info(msg)
return msg

if get_ratio(width, height) < 1.33:
msg = u'Image aspect ratio should be 1.33:1 at least.'
logger.info(msg)
return msg


def get_ratio(w, h):
"""Calculate aspect ratio."""
w = float(w)
h = float(h)
r = w % h or w
return '%s' % float((w / r) / (h / r))

0 comments on commit a80fe1b

Please sign in to comment.