def form_schema(self):
     return schema.Schema("FacebookPublicationForm", members = [
         schema.Collection("subset",
             items = schema.Reference(
                 type = Publishable,
                 required = True,
                 enumeration = lambda ctx: self.selection
             ),
             min = 1,
             default = schema.DynamicDefault(lambda: self.selection)
         ),
         schema.Collection("published_languages",
             items = schema.String(
                 translate_value = lambda value, language = None, **kwargs:
                     "" if not value 
                        else translations(value, language, **kwargs),
                 enumeration = lambda ctx: self.eligible_languages
             ),
             min = 1,
             default = schema.DynamicDefault(
                 lambda: self.eligible_languages
             )
         ),
         schema.Collection("publication_targets",
             items = schema.Reference(
                 type = FacebookPublicationTarget,
                 required = True,
                 enumeration = lambda ctx: self.allowed_publication_targets
             ),
             min = 1,
             default = schema.DynamicDefault(
                 lambda: self.allowed_publication_targets
             )
         )
     ])
    def form_model(self):
        
        from woost.extensions.staticsite import StaticSiteExtension
        extension = StaticSiteExtension.instance        
        
        site_languages = Configuration.instance.languages

        def allowed_destinations():
            return [
                destination 
                for destination in extension.destinations 
                if get_current_user().has_permission(
                    ExportationPermission,
                    destination = destination
                )
            ]

        return schema.Schema("ExportStaticSite", members = [
            schema.Reference(
                "snapshoter",
                type =
                    "woost.extensions.staticsite.staticsitesnapshoter."
                    "StaticSiteSnapShoter",
                required = True,
                enumeration = lambda ctx: extension.snapshoters,
                edit_control =
                    "cocktail.html.RadioSelector"
                    if len(allowed_destinations()) > 1
                    else "cocktail.html.HiddenInput",
                default = schema.DynamicDefault(lambda: extension.snapshoters[0])
            ),
            schema.Reference(
                "destination",
                type =
                    "woost.extensions.staticsite.staticsitedestination."
                    "StaticSiteDestination",
                required = True,
                enumeration = lambda ctx: allowed_destinations(),
                edit_control =
                    "cocktail.html.RadioSelector"
                    if len(allowed_destinations()) > 1
                    else "cocktail.html.HiddenInput",
                default = schema.DynamicDefault(lambda: allowed_destinations()[0])
            ),
            schema.Boolean(
                "update_only",
                required = True,
                default = True
            ),            
            schema.Boolean(
                "follow_links",
                required = True,
                default = True
            )            
        ])
Ejemplo n.º 3
0
class SignUpPage(Document):

    members_order = [
        "user_type", "roles", "confirmation_target",
        "confirmation_email_template"
    ]

    # Defines the persistent class that will be
    # used like schema in signup process
    user_type = schema.Reference(class_family=User,
                                 required=True,
                                 member_group="signup_process")

    # The collection of roles that will be applyed
    # to each instance (of user_type class) created throw
    # a signuppage
    roles = schema.Collection(
        items="woost.models.Role",
        related_end=schema.Collection(name="related_signup_pages",
                                      visible=False),
        member_group="signup_process",
        relation_constraints=lambda ctx: [excluded_roles()])

    # If is None, doesn't require an email confirmation
    # process to complete signup process
    confirmation_email_template = schema.Reference(
        type=EmailTemplate,
        related_end=schema.Collection(),
        member_group="signup_process")

    confirmation_target = schema.Reference(type="woost.models.Publishable",
                                           related_end=schema.Collection(),
                                           member_group="signup_process",
                                           required=True)

    default_template = schema.DynamicDefault(lambda: Template.get_instance(
        qname=u"woost.extensions.signup.signup_template"))

    default_controller = schema.DynamicDefault(lambda: Controller.get_instance(
        qname=u"woost.extensions.signup.signup_controller"))

    default_confirmation_email_template = schema.DynamicDefault(
        lambda: EmailTemplate.get_instance(
            qname=u"woost.extensions.signup.signup_confirmation_email_template"
        ))

    default_confirmation_target = schema.DynamicDefault(
        lambda: Publishable.get_instance(
            qname=u"woost.extensions.signup.signup_confirmation_target"))
class FacebookIdentityProvider(IdentityProvider):
    provider_name = "Facebook"
    user_identifier = "x_identity_facebook_user_id"

    members_order = [
        "client_id",
        "client_secret",
        "scope"
    ]

    client_id = schema.String(
        required=True,
        text_search=False
    )

    client_secret = schema.String(
        required=True,
        text_search=False
    )

    scope = schema.Collection(
        min=1,
        default=schema.DynamicDefault(lambda: ["public_profile", "email"]),
        items=schema.String()
    )

    def get_auth_url(self, target_url = None):
        return (
            "/facebook_oauth/%d/step1?%s" % (
                self.id,
                urlencode({
                    "target_url": target_url or get_request_url()
                })
            )
        )
Ejemplo n.º 5
0
class PayPalPaymentGateway(PaymentGateway, Implementation):

    instantiable = True

    default_label = schema.DynamicDefault(
        lambda: translations("PayPalPaymentGateway.label default"))

    members_order = [
        "business", "payment_successful_page", "payment_failed_page"
    ]

    business = schema.String(required=True,
                             shadows_attribute=True,
                             text_search=False)

    payment_successful_page = schema.Reference(type=Document,
                                               related_end=schema.Reference())

    payment_failed_page = schema.Reference(type=Document,
                                           related_end=schema.Reference())

    def get_payment_successful_url(self, payment):
        if self.payment_successful_page:
            return self.payment_successful_page.get_uri(
                host="!", parameters={"payment_id": payment.id})

    def get_payment_failed_url(self, payment):
        if self.payment_failed_page:
            return self.payment_failed_page.get_uri(
                host="!", parameters={"payment_id": payment.id})
Ejemplo n.º 6
0
class ChangeSet(PersistentObject):
    """A persistent record of a set of L{changes<Change>} performed on one or
    more CMS items."""

    members_order = "id", "author", "date", "changes"
    indexed = True

    changes = schema.Mapping(
        searchable=False,
        get_item_key=lambda change: change.target and change.target.id)

    author = schema.Reference(required=True, type="woost.models.User")

    date = schema.DateTime(required=True,
                           default=schema.DynamicDefault(datetime.now))

    _thread_data = local()

    @classgetter
    def current(cls):
        return getattr(cls._thread_data, "current", None)

    @classgetter
    def current_author(cls):
        cs = cls.current
        return cs and cs.author

    def begin(self):

        if self.current:
            raise TypeError("Can't begin a new changeset, another changeset "
                            "is already in place")

        self._thread_data.current = self

    def end(self):
        try:
            del self._thread_data.current
        except AttributeError:
            raise TypeError("Can't finalize the current changeset, there's no "
                            "changeset in place")

    def get_searchable_text(self, languages, visited_objects=None):

        if visited_objects is None:
            visited_objects = set()
        elif self in visited_objects:
            return

        visited_objects.add(self)

        # Concatenate the descriptions of change authors and targets
        for language in languages:
            if self.author:
                yield translations(self.author, language)
            for change in self.changes.itervalues():
                yield translations(change.target, language)
Ejemplo n.º 7
0
class Pasat4bPaymentGateway(PaymentGateway, Implementation):

    instantiable = True

    default_label = schema.DynamicDefault(
        lambda: translations("Pasat4bPaymentGateway.label default"))

    merchant_code = schema.String(required=True,
                                  shadows_attribute=True,
                                  text_search=False)
Ejemplo n.º 8
0
 def form_schema(self):
     return schema.Schema(
         "FacebookAlbumsForm",
         members=[
             schema.String("album_title", required=True),
             schema.String("album_description",
                           edit_control="cocktail.html.TextArea"),
             schema.Collection(
                 "subset",
                 items=schema.Reference(
                     type=File,
                     relation_constraints=[
                         File.resource_type.equal("image")
                     ],
                     required=True,
                     enumeration=lambda ctx: self.selection),
                 min=1,
                 default=schema.DynamicDefault(lambda: self.selection)),
             schema.Collection(
                 "photo_languages",
                 min=1,
                 items=schema.String(required=True,
                                     enumeration=lambda ctx: Configuration.
                                     instance.languages,
                                     translate_value=lambda value, language=
                                     None, **kwargs: ""
                                     if not value else translations(
                                         value, language, **kwargs)),
                 default=schema.DynamicDefault(
                     lambda: Configuration.instance.languages)),
             schema.Boolean("generate_story", required=True, default=True),
             schema.Collection(
                 "publication_targets",
                 items=schema.Reference(type=FacebookPublicationTarget,
                                        required=True,
                                        enumeration=lambda ctx: self.
                                        allowed_publication_targets),
                 min=1,
                 default=schema.DynamicDefault(
                     lambda: self.allowed_publication_targets))
         ])
Ejemplo n.º 9
0
class SISPaymentGateway(PaymentGateway, Implementation):

    instantiable = True

    default_label = schema.DynamicDefault(
        lambda: translations("SISPaymentGateway.label default"))

    members_order = [
        "merchant_name", "merchant_code", "merchant_terminal",
        "merchant_secret_key", "pay_methods", "payment_successful_page",
        "payment_failed_page"
    ]

    merchant_code = schema.String(required=True,
                                  shadows_attribute=True,
                                  text_search=False)

    merchant_name = schema.String(shadows_attribute=True, text_search=False)

    merchant_terminal = schema.String(required=True,
                                      shadows_attribute=True,
                                      text_search=False)

    merchant_secret_key = schema.String(required=True,
                                        shadows_attribute=True,
                                        text_search=False)

    pay_methods = schema.Collection(
        shadows_attribute = True,
        items = schema.String(
            enumeration = ["T", "D", "R"],
            translate_value = lambda value, language = None, **kwargs: \
                translations("SISPaymentGateway.pay_methods=%s" % (value,))
        ),
        edit_control = "cocktail.html.CheckList"
    )

    payment_successful_page = schema.Reference(type=Document,
                                               related_end=schema.Reference())

    payment_failed_page = schema.Reference(type=Document,
                                           related_end=schema.Reference())

    def get_payment_successful_url(self, payment):
        if self.payment_successful_page:
            return self.payment_successful_page.get_uri(
                host="!", parameters={"paymend_id": payment.id})

    def get_payment_failed_url(self, payment):
        if self.payment_failed_page:
            return self.payment_failed_page.get_uri(
                host="!", parameters={"paymend_id": payment.id})
Ejemplo n.º 10
0
def add_url_shortener_reference(e):
    if e.source.enabled:
        TwitterPublicationTarget.add_member(
            schema.Reference(
                "url_shortener",
                shadows_attribute=True,
                type=URLShortener,
                related_end=schema.Collection(),
                listed_by_default=False,

                # Default to the first defined service, if one exists
                default=schema.DynamicDefault(
                    lambda: first(URLShortener.select()))))
Ejemplo n.º 11
0
class CampaignMonitorSubscriptionPage(Document):
    
    members_order = "lists", "subscription_form", "body"

    default_template = schema.DynamicDefault(
        lambda: Template.get_instance(
            qname = u"woost.extensions.campaignmonitor.subscription_template"
        )
    )   

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(
            qname = u"woost.extensions.campaignmonitor.subscription_controller"
        )
    )

    body = schema.String(
        translated = True,
        listed_by_default = False,    
        edit_control = "woost.views.RichTextEditor",                                                                                                                                                           
        member_group = "content"
    )

    lists = schema.Collection(
        items = schema.Reference(
            type = CampaignMonitorList
        ),
        member_group = "content",
        listed_by_default = False
    )   

    subscription_form = schema.String(
        member_group = "content",
        default = \
            "woost.extensions.campaignmonitor.subscriptionform.SubscriptionForm",
        text_search = False
    )
Ejemplo n.º 12
0
class UserForm(Document):

    groups_order = list(Document.groups_order)
    groups_order.insert(groups_order.index("content") + 1, "form")

    members_order = [
        "form_model", "excluded_members", "should_save_instances",
        "redirection", "email_notifications"
    ]

    default_controller = schema.DynamicDefault(lambda: Controller.get_instance(
        qname="woost.extensions.usermodels.user_form_controller"))

    default_template = schema.DynamicDefault(lambda: Template.get_instance(
        qname="woost.extensions.usermodels.user_form_template"))

    form_model = schema.Reference(required=True,
                                  class_family="woost.models.Item",
                                  member_group="form")

    excluded_members = schema.Collection(items=schema.String(),
                                         edit_control="cocktail.html.TextArea",
                                         member_group="form")

    should_save_instances = schema.Boolean(required=True,
                                           default=True,
                                           member_group="form")

    redirection = schema.Reference(type=Publishable,
                                   related_end=schema.Collection(),
                                   member_group="form")

    email_notifications = schema.Collection(
        items=schema.Reference(type=EmailTemplate),
        related_end=schema.Collection(),
        member_group="form")
Ejemplo n.º 13
0
class CampaignMonitorList(Item):

    visible_from_root = False

    members_order = [
        "list_id",
        "pending_page",
        "confirmation_success_page",
        "unsubscribe_page",
    ]   

    default_pending_page = schema.DynamicDefault(
        lambda: StandardPage.get_instance(
            qname = u"woost.extensions.campaignmonitor.pending_page"
        )
    )   

    title = schema.String(
        editable = False,
        listed_by_default = False,
        descriptive = True
    )

    list_id = schema.String(
        unique = True,
        editable = False,
        text_search = False
    )

    unsubscribe_page = schema.Reference(
        type = "woost.models.Publishable",
        related_end = schema.Collection()
    )

    pending_page = schema.Reference(
        required = True,
        type = "woost.models.Publishable",
        related_end = schema.Collection()
    )

    confirmation_success_page = schema.Reference(
        type = "woost.models.Publishable",
        related_end = schema.Collection()
    )
Ejemplo n.º 14
0
class URI(Publishable):

    instantiable = True
    type_group = "resource"

    groups_order = ["content"]

    members_order = ["title", "uri", "language_specific_uri"]

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname="woost.uri_controller"))

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          member_group="content")

    uri = schema.String(indexed=True, member_group="content")

    language_specific_uri = schema.String(translated=True,
                                          member_group="content")

    def get_uri(self,
                path=None,
                parameters=None,
                language=None,
                host=None,
                encode=True):

        uri = self.language_specific_uri or self.uri

        if uri is not None:

            if path:
                uri = make_uri(uri, *path)

            if parameters:
                uri = make_uri(uri, **parameters)

            uri = self._fix_uri(uri, host, encode)

        return uri
Ejemplo n.º 15
0
class TextFile(Publishable):

    instantiable = True
    per_language_publication = False
    default_mime_type = "text/plain"
    default_hidden = True

    default_controller = schema.DynamicDefault(lambda: Controller.get_instance(
        qname="woost.extensions.textfile.TextFileController"))

    members_order = ["title", "content"]

    title = schema.String(translated=True,
                          descriptive=True,
                          listed_by_default=False,
                          member_group="content")

    content = schema.String(edit_control="cocktail.html.TextArea",
                            listed_by_default=False,
                            member_group="content")
Ejemplo n.º 16
0
class News(Document):

    members_order = ["news_date", "image", "summary", "blocks"]

    news_date = schema.Date(required=True,
                            indexed=True,
                            default=schema.DynamicDefault(date.today),
                            member_group="content")

    image = schema.Reference(type=File,
                             related_end=schema.Collection(),
                             relation_constraints={"resource_type": "image"},
                             member_group="content")

    summary = schema.String(edit_control="woost.views.RichTextEditor",
                            listed_by_default=False,
                            translated=True,
                            member_group="content")

    blocks = Slot()
Ejemplo n.º 17
0
class Product(Publishable):

    instantiable = False
    view_class = None

    members_order = [
        "price",
        "categories",
        "entries"
    ]

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname = "woost.product_controller")
    )

    price = schema.Decimal(
        required = True,
        default = Decimal("0")
    )
    
    categories = schema.Collection(
        items = "woost.extensions.shop.productcategory.ProductCategory",
        bidirectional = True
    )

    entries = schema.Collection(
        items = "woost.extensions.shop.shoporderentry.ShopOrderEntry",
        bidirectional = True,
        visible = False,
        block_delete = True
    )

    def discounts(self):
        """Returns the discounts that can be applied to the product.        
        @rtype: L{Product<woost.extensions.shop.product.Product>}
        """
        from woost.extensions.shop import ShopExtension
        return [discount
                for discount in ShopExtension.instance.discounts
                if discount.applies_to(self)]
Ejemplo n.º 18
0
class SlideShowBlock(Block):

    instantiable = True
    view_class = "woost.views.SlideShowBlockView"

    groups_order = [
        "content", "transition_settings", "controls", "behavior", "html",
        "administration"
    ]

    members_order = [
        "element_type", "slides", "autoplay", "interval", "transition_effect",
        "transition_duration", "navigation_controls", "bullet_controls",
        "bullet_view_class", "bullet_image_factory"
    ]

    element_type = ElementType(enumeration=list(ElementType.enumeration),
                               member_group="content")

    for et in ("nav", "dd"):
        try:
            element_type.enumeration.remove(et)
        except:
            pass

    slides = Slot()

    autoplay = schema.Boolean(required=True,
                              default=True,
                              member_group="transition_settings")

    interval = schema.Integer(required=autoplay,
                              default=3000,
                              min=0,
                              member_group="transition_settings")

    transition_effect = schema.String(required=True,
                                      default="fade",
                                      enumeration=["fade", "topBottomSlide"],
                                      member_group="transition_settings")

    transition_duration = schema.Integer(required=True,
                                         default=500,
                                         min=0,
                                         member_group="transition_settings")

    navigation_controls = schema.Boolean(required=True,
                                         default=False,
                                         member_group="controls")

    bullet_controls = schema.Boolean(required=True,
                                     default=False,
                                     member_group="controls")

    bullet_view_class = schema.String(
        required=True,
        default="woost.views.SlideShowButtonBullet",
        enumeration=[
            "woost.views.SlideShowButtonBullet",
            "woost.views.SlideShowTextBullet",
            "woost.views.SlideShowImageBullet",
            "woost.views.SlideShowTextAndImageBullet"
        ],
        member_group="controls")

    bullet_image_factory = schema.Reference(
        type=ImageFactory,
        related_end=schema.Collection(),
        required=True,
        default=schema.DynamicDefault(lambda: ImageFactory.get_instance(
            identifier="image_gallery_thumbnail")),
        member_group="controls")

    def init_view(self, view):

        Block.init_view(self, view)

        view.tag = self.element_type
        view.autoplay = self.autoplay
        view.interval = self.interval
        view.transition_effect = self.transition_effect
        view.transition_duration = self.transition_duration
        view.navigation_controls = self.navigation_controls
        view.bullet_controls = self.bullet_controls
        view.bullet_view_class = self.bullet_view_class
        view.bullet_image_factory = self.bullet_image_factory

        for block_view in create_block_views(self.slides):
            view.slides.append(block_view)
from cocktail import schema
from cocktail.html.datadisplay import display_factory
from cocktail.iteration import first
from .configuration import Configuration
from .rendering import ImageFactory

def _iter_block_image_factories():
    for factory in Configuration.instance.image_factories:
        if factory.applicable_to_blocks:
            yield factory

def _block_image_factories_enumeration(ctx):
    return list(_iter_block_image_factories())

_block_image_factories_default = schema.DynamicDefault(
    lambda: first(_iter_block_image_factories())
)

_mandatory_dropdown = display_factory(
    "cocktail.html.DropdownSelector",
    empty_option_displayed = False
)


class BlockImageFactoryReference(schema.Reference):

    def __init__(self, *args, **kwargs):
        
        kwargs.setdefault("required", True)
        kwargs.setdefault("type", ImageFactory)
        kwargs.setdefault("enumeration", _block_image_factories_enumeration)
Ejemplo n.º 20
0
class ECommerceOrder(Item):

    payment_types_completed_status = {
        "payment_gateway": "accepted",
        "transfer": "payment_pending",
        "cash_on_delivery": "payment_pending"
    }

    incoming = Event(doc="""
        An event triggered when a new order is received.
        """)

    completed = Event(doc="""
        An event triggered when an order is completed.
        """)

    groups_order = ["shipping_info", "billing"]

    members_order = [
        "customer", "address", "town", "region", "country", "postal_code",
        "language", "status", "purchases", "payment_type", "total_price",
        "pricing", "total_shipping_costs", "shipping_costs", "total_taxes",
        "taxes", "total"
    ]

    customer = schema.Reference(
        type=User,
        related_end=schema.Collection(),
        required=True,
        default=schema.DynamicDefault(get_current_user))

    address = schema.String(member_group="shipping_info",
                            required=True,
                            listed_by_default=False)

    town = schema.String(member_group="shipping_info",
                         required=True,
                         listed_by_default=False)

    region = schema.String(member_group="shipping_info",
                           required=True,
                           listed_by_default=False)

    country = schema.Reference(
        member_group="shipping_info",
        type=Location,
        relation_constraints=[Location.location_type.equal("country")],
        default_order="location_name",
        related_end=schema.Collection(),
        required=True,
        listed_by_default=False,
        user_filter="cocktail.controllers.userfilter.MultipleChoiceFilter")

    postal_code = schema.String(member_group="shipping_info",
                                required=True,
                                listed_by_default=False)

    language = schema.String(
        required=True,
        format="^[a-z]{2}$",
        editable=False,
        default=schema.DynamicDefault(get_language),
        text_search=False,
        translate_value=lambda value, language=None, **kwargs: u""
        if not value else translations(value, language, **kwargs))

    status = schema.String(
        required=True,
        indexed=True,
        enumeration=[
            "shopping", "payment_pending", "accepted", "failed", "refund"
        ],
        default="shopping",
        text_search=False,
        translate_value=lambda value, language=None, **kwargs: u""
        if not value else translations("ECommerceOrder.status-" + value,
                                       language, **kwargs))

    purchases = schema.Collection(
        items="woost.extensions.ecommerce.ecommercepurchase."
        "ECommercePurchase",
        integral=True,
        bidirectional=True,
        min=1)

    payment_type = schema.String(
        member_group="billing",
        required=True,
        translate_value=lambda value, language=None, **kwargs: translations(
            "ECommerceOrder.payment_type-%s" % value, language=language),
        default=schema.DynamicDefault(_get_default_payment_type),
        text_search=False,
        edit_control="cocktail.html.RadioSelector",
        listed_by_default=False)

    total_price = schema.Decimal(member_group="billing",
                                 editable=False,
                                 listed_by_default=False,
                                 translate_value=_translate_amount)

    pricing = schema.Collection(
        member_group="billing",
        items=schema.Reference(type=ECommerceBillingConcept),
        related_end=schema.Collection(block_delete=True),
        editable=False)

    total_shipping_costs = schema.Decimal(member_group="billing",
                                          editable=False,
                                          listed_by_default=False,
                                          translate_value=_translate_amount)

    shipping_costs = schema.Collection(
        member_group="billing",
        items=schema.Reference(type=ECommerceBillingConcept),
        related_end=schema.Collection(block_delete=True),
        editable=False)

    total_taxes = schema.Decimal(member_group="billing",
                                 editable=False,
                                 listed_by_default=False,
                                 translate_value=_translate_amount)

    taxes = schema.Collection(
        member_group="billing",
        items=schema.Reference(type=ECommerceBillingConcept),
        related_end=schema.Collection(block_delete=True),
        editable=False)

    total = schema.Decimal(member_group="billing",
                           editable=False,
                           translate_value=_translate_amount)

    def calculate_cost(self,
                       apply_pricing=True,
                       apply_shipping_costs=True,
                       apply_taxes=True):
        """Calculates the costs for the order.
        :rtype: dict
        """
        from woost.extensions.ecommerce import ECommerceExtension
        extension = ECommerceExtension.instance

        order_costs = {
            "price": {
                "cost": Decimal("0.00"),
                "percentage": Decimal("0.00"),
                "concepts": []
            },
            "shipping_costs": {
                "cost": Decimal("0.00"),
                "percentage": Decimal("0.00"),
                "concepts": []
            },
            "taxes": {
                "cost": Decimal("0.00"),
                "percentage": Decimal("0.00"),
                "concepts": []
            },
            "purchases": {}
        }

        # Per purchase costs:
        for purchase in self.purchases:
            purchase_costs = purchase.calculate_costs(
                apply_pricing=apply_pricing,
                apply_shipping_costs=apply_shipping_costs,
                apply_taxes=apply_taxes)
            order_costs["purchases"][purchase] = purchase_costs

            order_costs["price"]["cost"] += purchase_costs["price"]["total"]
            order_costs["shipping_costs"]["cost"] += \
                purchase_costs["shipping_costs"]["total"]
            order_costs["taxes"]["cost"] += purchase_costs["taxes"]["total"]

        # Order price
        order_price = order_costs["price"]

        if apply_pricing:
            for pricing in extension.pricing:
                if pricing.applies_to(self):
                    pricing.apply(self, order_price)

        order_price["cost"] += \
            order_price["cost"] * order_price["percentage"] / 100

        order_price["total"] = order_price["cost"]

        # Order shipping costs
        order_shipping_costs = order_costs["shipping_costs"]

        if apply_shipping_costs:
            for shipping_cost in extension.shipping_costs:
                if shipping_cost.applies_to(self):
                    shipping_cost.apply(self, order_shipping_costs)

        order_shipping_costs["total"] = (
            order_shipping_costs["cost"] +
            order_price["total"] * order_shipping_costs["percentage"] / 100)

        # Order taxes
        order_taxes = order_costs["taxes"]

        if apply_taxes:
            for tax in extension.taxes:
                if tax.applies_to(self):
                    tax.apply(self, order_taxes)

        order_taxes["total"] = (
            order_taxes["cost"] +
            order_price["total"] * order_taxes["percentage"] / 100)

        # Total
        order_costs["total"] = (order_price["total"] +
                                order_shipping_costs["total"] +
                                order_taxes["total"])

        return order_costs

    def update_cost(self,
                    apply_pricing=True,
                    apply_shipping_costs=True,
                    apply_taxes=True):
        costs = self.calculate_cost(apply_pricing=apply_pricing,
                                    apply_shipping_costs=apply_shipping_costs,
                                    apply_taxes=apply_taxes)

        self.total_price = costs["price"]["total"]
        self.pricing = list(costs["price"]["concepts"])

        self.total_shipping_costs = costs["shipping_costs"]["total"]
        self.shipping_costs = list(costs["shipping_costs"]["concepts"])

        self.total_taxes = costs["taxes"]["total"]
        self.taxes = list(costs["taxes"]["concepts"])

        self.total = costs["total"]

        for purchase, purchase_costs in costs["purchases"].iteritems():
            purchase.total_price = purchase_costs["price"]["total"]
            purchase.pricing = list(purchase_costs["price"]["concepts"])
            self.pricing.extend(purchase.pricing)

            purchase.total_shipping_costs = \
                purchase_costs["shipping_costs"]["total"]
            purchase.shipping_costs = \
                list(purchase_costs["shipping_costs"]["concepts"])
            self.shipping_costs.extend(purchase.shipping_costs)

            purchase.total_taxes = purchase_costs["taxes"]["total"]
            purchase.taxes = list(purchase_costs["taxes"]["concepts"])
            self.taxes.extend(purchase.taxes)

            purchase.total = purchase_costs["total"]

    def count_units(self):
        return sum(purchase.quantity for purchase in self.purchases)

    def get_weight(self):
        return sum(purchase.get_weight() for purchase in self.purchases)

    def add_purchase(self, purchase):
        for order_purchase in self.purchases:
            if order_purchase.__class__ is purchase.__class__ \
            and order_purchase.product is purchase.product \
            and all(
                order_purchase.get(option) == purchase.get(option)
                for option in purchase.get_options()
                if option.name != "quantity"
            ):
                order_purchase.quantity += purchase.quantity
                purchase.product = None
                if purchase.is_inserted:
                    purchase.delete()
                break
        else:
            self.purchases.append(purchase)

    @classmethod
    def get_public_schema(cls):
        public_schema = schema.Schema("OrderCheckoutSummary")
        cls.get_public_adapter().export_schema(cls, public_schema)

        payment_type = public_schema.get_member("payment_type")
        if payment_type:
            payments = PaymentsExtension.instance

            if payments.enabled and payments.payment_gateway:

                translate_value = payment_type.translate_value

                def payment_type_translate_value(value,
                                                 language=None,
                                                 **kwargs):
                    if value == "payment_gateway":
                        return payments.payment_gateway.label
                    else:
                        return translate_value(value,
                                               language=language,
                                               **kwargs)

                payment_type.translate_value = payment_type_translate_value

        return public_schema

    @classmethod
    def get_public_adapter(cls):
        from woost.extensions.ecommerce import ECommerceExtension

        user = get_current_user()
        adapter = schema.Adapter()
        adapter.exclude(["customer", "status", "purchases"])
        adapter.exclude([
            member.name for member in cls.members().itervalues()
            if not member.visible or not member.editable
            or not issubclass(member.schema, ECommerceOrder)
            or not user.has_permission(ModifyMemberPermission, member=member)
        ])
        if len(ECommerceExtension.instance.payment_types) == 1:
            adapter.exclude(["payment_type"])
        return adapter

    @property
    def is_completed(self):
        return self.status \
        and self.status == self.payment_types_completed_status.get(
            self.payment_type
        )

    @event_handler
    def handle_changed(cls, event):

        item = event.source
        member = event.member

        if member.name == "status":

            if event.previous_value == "shopping" \
            and event.value in ("payment_pending", "accepted"):
                item.incoming()

            if item.is_completed:
                item.completed()

    def get_description_for_gateway(self):
        site_name = Configuration.instance.get_setting("site_name")
        if site_name:
            return translations(
                "woost.extensions.ECommerceOrder description for gateway"
            ) % site_name
        else:
            return translations(self)
Ejemplo n.º 21
0
    member = OpenGraphType.category


Publishable.add_member(
    schema.Boolean("x_opengraph_enabled",
                   required=True,
                   default=True,
                   listed_by_default=False,
                   member_group="meta.x_opengraph"))

Publishable.add_member(
    schema.Reference("x_opengraph_type",
                     type=OpenGraphType,
                     required=Publishable["x_opengraph_enabled"],
                     related_end=schema.Collection(block_delete=True),
                     default=schema.DynamicDefault(
                         lambda: OpenGraphType.get_instance(code="article")),
                     indexed=True,
                     listed_by_default=False,
                     member_group="meta.x_opengraph"))


def _get_publishable_properties(self):

    properties = {
        "og:title": translations(self),
        "og:type": self.x_opengraph_type.code,
        "og:url": self.get_uri(host="!")
    }

    description = self.x_opengraph_get_description()
    if description:
Ejemplo n.º 22
0
class TextBlock(Block):

    instantiable = True
    view_class = "woost.views.TextBlockView"
    block_display = "woost.views.TextBlockDisplay"
    edit_form = "woost.views.TextBlockForm"

    groups_order = [
        "content",
        "images",
        "link",
        "behavior",
        "html",
        "administration"
    ]

    members_order = [
        "element_type",
        "text",
        "images",
        "image_alignment",
        "image_thumbnail_factory",
        "image_close_up_enabled",
        "image_close_up_factory",
        "image_close_up_preload",
        "image_labels_visible",
        "image_original_link_visible",
        "link_destination",
        "link_parameters",
        "link_opens_in_new_window"
    ]

    element_type = ElementType(
        member_group = "content"
    )

    text = schema.String(
        edit_control = "woost.views.RichTextEditor",
        translated = True,
        member_group = "content"
    )

    images = schema.Collection(
        items = schema.Reference(type = File),
        related_end = schema.Collection(),
        relation_constraints = [File.resource_type.equal("image")],
        member_group = "images",
        invalidates_cache = True
    )

    image_alignment = schema.String(
        required = True,
        default = "float_top_left",
        enumeration = [
            "float_top_left",
            "float_top_right",
            "column_left",
            "column_right",
            "top_left",
            "top_right",
            "bottom_left",
            "center_top",
            "center_bottom",
            "inline",
            "background",
            "fallback"
        ],
        edit_control = _mandatory_dropdown,
        member_group = "images"
    )

    image_thumbnail_factory = BlockImageFactoryReference(
        required = True,
        member_group = "images"
    )

    image_close_up_enabled = schema.Boolean(
        required = True,
        default = False,
        member_group = "images"
    )

    image_close_up_factory = BlockImageFactoryReference(
        required = True,
        default = schema.DynamicDefault(
            lambda: ImageFactory.get_instance(identifier = "gallery_close_up")
        ),
        member_group = "images"
    )

    image_close_up_preload = schema.Boolean(
        required = True,
        default = True,
        member_group = "images"
    )

    image_labels_visible = schema.Boolean(
        required = True,
        default = False,
        member_group = "images"
    )

    image_original_link_visible = schema.Boolean(
        required = True,
        default = False,
        member_group = "images"
    )

    def get_block_image(self):
        for image in self.images:
            return image
        else:
            return Block.get_block_image(self)

    link_destination = schema.Reference(
        type = Publishable,
        related_end = schema.Collection(),
        member_group = "link",
        invalidates_cache = True
    )

    link_parameters = schema.String(
        edit_control = "cocktail.html.TextArea",
        member_group = "link"
    )

    link_opens_in_new_window = schema.Boolean(
        default = False,
        required = True,
        member_group = "link"
    )

    def init_view(self, view):
        Block.init_view(self, view)
        
        if self.element_type == "dd":
            view.tag = None
            view.content_wrapper.tag = "dd"
        else:
            view.tag = self.element_type

    def get_block_proxy(self, view):
        if self.element_type == "dd":
            return view.content_wrapper
        return view
Ejemplo n.º 23
0
class File(Publishable):

    instantiable = True
    cacheable = False
    type_group = "resource"

    edit_node_class = \
        "woost.controllers.backoffice.fileeditnode.FileEditNode"
    backoffice_heading_view = "woost.views.BackOfficeFileHeading"
    video_player = "cocktail.html.MediaElementVideo"

    default_mime_type = None

    default_encoding = None

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname="woost.file_controller"))

    members_order = ["title", "file_name", "file_size", "file_hash"]

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          member_group="content")

    file_name = schema.String(required=True,
                              editable=False,
                              member_group="content")

    file_size = schema.Integer(
        required=True,
        editable=False,
        translate_value=lambda size, language=None, **kwargs: ""
        if size in (None, "") else format_bytes(size),
        min=0,
        member_group="content")

    file_hash = schema.String(visible=False,
                              searchable=False,
                              text_search=False,
                              member_group="content")

    @property
    def file_extension(self):
        return os.path.splitext(self.file_name)[1]

    @property
    def file_path(self):
        return app.path("upload", str(self.id))

    @classmethod
    def from_path(cls,
                  path,
                  dest=None,
                  languages=None,
                  hash=None,
                  encoding="utf-8",
                  download_temp_folder=None,
                  redownload=False):
        """Imports a file into the site.
        
        @param path: The path to the file that should be imported.
        @type path: str

        @param dest: The base path where the file should be copied (should match
            the upload folder for the application).
        @type dest: str

        @param languages: The set of languages that the created file will be
            translated into.
        @type languages: str set
       
        @return: The created file.
        @rtype: L{File}
        """

        # The default behavior is to translate created files into all the languages
        # defined by the site
        if languages is None:
            from woost.models import Configuration
            languages = Configuration.instance.languages

        file_name = os.path.split(path)[1]
        title, ext = os.path.splitext(file_name)

        # Download remote files
        if "://" in path:
            if not download_temp_folder:
                download_temp_folder = mkdtemp()

            temp_path = os.path.join(download_temp_folder, file_name)

            if redownload or not os.path.exists(temp_path):
                response = urlopen(path)
                with open(temp_path, "w") as temp_file:
                    copyfileobj(response, temp_file)

            path = temp_path

        if encoding:
            if isinstance(title, str):
                title = title.decode(encoding)
            if isinstance(file_name, str):
                file_name = file_name.decode(encoding)

        title = title.replace("_", " ").replace("-", " ")
        title = title[0].upper() + title[1:]

        file = cls()

        file.file_size = os.stat(path).st_size
        file.file_hash = hash or file_hash(path)
        file.file_name = file_name

        # Infer the file's MIME type
        mime_type = guess_type(file_name, strict=False)
        if mime_type:
            file.mime_type = mime_type[0]

        for language in languages:
            file.set("title", title, language)

        if dest is None:
            upload_path = file.file_path
        else:
            upload_path = os.path.join(dest, str(file.id))

        copy(path, upload_path)

        return file
class GoogleIdentityProvider(IdentityProvider):

    provider_name = "Google"
    user_identifier = "x_identity_google_user_id"

    members_order = ["client_id", "client_secret", "scope", "access_type"]

    client_id = schema.String(required=True, text_search=False)

    client_secret = schema.String(required=True, text_search=False)

    scope = schema.Collection(
        min=1,
        default=schema.DynamicDefault(lambda: ["profile", "email"]),
        items=schema.String())

    access_type = schema.String(required=True,
                                default="online",
                                enumeration=["online", "offline"],
                                edit_control="cocktail.html.RadioSelector")

    def get_auth_url(self, target_url=None):
        return ("/google_oauth/%d/step1?%s" %
                (self.id,
                 urllib.parse.urlencode(
                     {"target_url": target_url or str(get_request_url())})))

    def get_refresh_token_url(self, redirect_uri=None):
        """
        Produces the URL to initiate a browser driven request to get a refresh
        code.
        """
        OAUTH_URL = "https://accounts.google.com/o/oauth2/auth"

        if not redirect_uri:
            website = (app.website or Configuration.instance.websites[0])
            redirect_uri = "http://%s/google_oauth/%d/refresh_token" % (
                website.hosts[0], self.id)

        params = {
            "client_id": self.client_id,
            "redirect_uri": redirect_uri,
            "scope": " ".join(self.scope),
            "response_type": "code",
            "access_type": self.access_type,
            "approval_prompt": "force"
        }

        return "{}?{}".format(OAUTH_URL, urllib.parse.urlencode(params))

    def get_refresh_token_from_browser(self, redirect_uri=None):
        """
        Opens the browser to get user authorization and shows the
        authorization code.
        """
        import webbrowser
        url = self.get_refresh_token_url(redirect_uri)
        webbrowser.open(url)

    def get_refresh_token(self, code, redirect_uri=None):
        """
        Gets an authorization token with access_token and refresh_token from
        an authorization code.

        :param code: A valid authorization code with access_type offline
        :return: A dict representing the authorization token. The
        'access_token' key is a valid access token and the 'refresh_token'
        key can be used to generate new valid access tokens
        """
        TOKEN_URL = "https://accounts.google.com/o/oauth2/token"

        if not redirect_uri:
            website = (app.website or Configuration.instance.websites[0])
            redirect_uri = "http://%s/google_oauth/%d/refresh_token" % (
                website.hosts[0], self.id)

        params = {
            "code": code,
            "client_id": self.client_id,
            "client_secret": self.client_secret,
            "redirect_uri": redirect_uri,
            "grant_type": "authorization_code"
        }

        request = urllib.request.Request(url=TOKEN_URL,
                                         data=urllib.parse.urlencode(params))
        json_file = urllib.request.urlopen(request).read()
        auth_token = json.loads(json_file)

        if self.debug_mode:
            print(styled("Google refresh token:", "magenta"), auth_token)

        return auth_token

    def get_access_token_from_refresh_token(self, refresh_token):
        """
        Gets a new access token from a refresh token.

        :return: A dict respresenting an access token. Its 'access_token' key
        is a valid access token
        """
        TOKEN_URL = "https://accounts.google.com/o/oauth2/token"

        params = {
            "client_id": self.client_id,
            "client_secret": self.client_secret,
            "refresh_token": refresh_token,
            "grant_type": "refresh_token"
        }

        request = urllib.request.Request(url=TOKEN_URL,
                                         data=urllib.parse.urlencode(params))

        try:
            json_file = urllib.request.urlopen(request).read()
        except urllib.error.HTTPError as e:
            if self.debug_mode:
                print(
                    styled(
                        "Error while obtaining a Google access token from a "
                        "refresh token:", "magenta"))
                print(e.read())
            raise

        access_token = json.loads(json_file)

        if self.debug_mode:
            print(styled("Google access token from refresh token:", "magenta"),
                  end=' ')
            print(access_token)

        return access_token
Ejemplo n.º 25
0
class User(Item):
    """An application user.

    @ivar anonymous: Indicates if this is the user that represents
        anonymous users.

        To handle anonymous access to the application, an instance of the
        User class is designated to represent anonymous users. This allows
        uniform treatment of both anonymous and authenticated access (ie.
        authorization checks).
        
        This property indicates if the user it is invoked on is the
        instance used to represent anonymous users.

    @type anonymous: bool

    @ivar encryption_method: The hashing algorithm used to encrypt user
        passwords. Should be a reference to one of the algorithms provided
        by the L{hashlib} module.
    """
    type_group = "users"
    edit_form = "woost.views.UserForm"
    edit_node_class = \
        "woost.controllers.backoffice.usereditnode.UserEditNode"

    encryption_method = sha1

    anonymous = False

    members_order = ["enabled", "email", "password", "prefered_language"]

    email = schema.String(required=True,
                          unique=True,
                          descriptive=True,
                          max=255,
                          indexed=True,
                          format="^.+@.+$")

    password = schema.String(required=True,
                             listable=False,
                             listed_by_default=False,
                             searchable=False,
                             text_search=False,
                             synchronizable=False,
                             min=8,
                             visible_in_detail_view=False,
                             edit_control="cocktail.html.PasswordBox")

    def _backoffice_language_default():
        from woost.models.configuration import Configuration
        return Configuration.instance.backoffice_language

    def _backoffice_language_enumeration(ctx):
        from woost.models.configuration import Configuration
        return Configuration.backoffice_language.enumeration

    prefered_language = schema.String(
        required=True,
        default=schema.DynamicDefault(_backoffice_language_default),
        enumeration=_backoffice_language_enumeration,
        translate_value=lambda value, language=None, **kwargs: ""
        if value is None else translations(value, language, **kwargs),
        text_search=False)

    del _backoffice_language_default
    del _backoffice_language_enumeration

    roles = schema.Collection(items="woost.models.Role", bidirectional=True)

    enabled = schema.Boolean(required=True, default=True)

    @classmethod
    def encryption(cls, data):

        if cls.encryption_method:

            if isinstance(data, unicode):
                data = data.encode("utf-8")

            data = cls.encryption_method(data).hexdigest()

        return data

    @event_handler
    def handle_changing(cls, event):

        if event.member is cls.password \
        and event.value is not None:
            event.value = cls.encryption(event.value)

    def test_password(self, password):
        """Indicates if the user's password matches the given string.
        
        @param password: An unencrypted string to tests against the user's
            encrypted password.
        @type password: str

        @return: True if the passwords match, False otherwise.
        @rtype: bool
        """
        if password:
            return self.encryption(password) == self.password
        else:
            return not self.password

    def iter_roles(self, recursive=True):
        """Obtains all the roles that apply to the user.

        The following roles can be yielded:
        
            * The user's L{explicit roles<roles>} will be yielded if defined
            * An 'authenticated' role will be yielded if the user is not
              L{anonymous}
            * An 'everybody' role that applies to all users will always be
              yielded

        Roles are sorted in descending relevancy order.

        @return: An iterable sequence of roles that apply to the user.
        @rtype: L{Role}
        """
        explicit_roles = self.roles
        if explicit_roles:
            if recursive:
                for role in explicit_roles:
                    for ancestor_role in role.iter_roles():
                        yield ancestor_role
            else:
                for role in explicit_roles:
                    yield role

        for role in self.iter_implicit_roles():
            yield role

    def iter_implicit_roles(self):

        if not self.anonymous:
            yield Role.require_instance(qname="woost.authenticated")

        yield Role.require_instance(qname="woost.everybody")

    def has_role(self, role):
        """Determines if the user has been granted the indicated role.

        This takes into account inherited and implicit roles.

        @return: True if the user possesses the given role, False otherwise.
        @rtype: bool
        """
        for user_role in self.iter_roles():
            if user_role is role:
                return True

        return False

    def iter_permissions(self, permission_type=None):
        """Iterates over the permissions granted to the user's roles.

        This method yields all permissions that are granted to any of the
        user's roles.

        @param permission_type: If given, restricts the list of returned
            permissions to those of the given type (or a subclass of that
            type). By default, all permissions are yielded, regardless of their
            type.
        @type permission_type: L{Permission} subclass

        @return: An iterable sequence of permissions granted to any of the
            user's roles.
        @rtype: L{Permission} sequence
        """
        for role in self.iter_roles(False):
            for permission in role.iter_permissions(permission_type):
                yield permission

    def has_permission(self, permission_type, verbose=None, **context):
        """Determines if the user is given permission to perform an action.

        @param permission_type: The kind of permission to assert.
        @type permission_type: L{Permission} subclass

        @param verbose: A boolean flag that enables or disables on screen
            reporting of the checks executed by this method. Can help debugging
            authorization issues. When set, overrides the value of the module
            L{verbose} flag.
        @type verbose: bool

        @param context: Keyword parameters to supply to each tested permission.
            Each parameter will be forwarded to the permission's
            L{match<woost.models.permission.Permission.match>} method. Each
            subclass or L{Permission<woost.models.permission.Permission>}
            can define its set of required parameters, and all of its
            subclasses must implement exactly that set.

        @return: True if the user is granted permission, else False.
        @rtype: bool
        """
        if verbose is None:
            verbose = globals()["verbose"]

        if verbose:
            role = None
            print permission_check_style(translations(permission_type.name))
            print permission_param_style("user", translations(self))

            for key, value in context.iteritems():
                if isinstance(value, type):
                    value = translations(value.name)
                else:
                    trans = translations(value)
                    if trans and isinstance(value, Item):
                        value = u"%s (%s)" % (unicode(value), trans)
                    else:
                        value = trans or unicode(value)

                print permission_param_style(key, value)

        permissions = self.iter_permissions(permission_type)

        for permission in permissions:

            if verbose:
                new_role = permission.role
                if new_role is not role:
                    role = new_role
                    print role_style(translations(role))

                print permission_style(
                    "#%d. %s" % (permission.id, translations(permission)))

            if permission.match(verbose=verbose, **context):

                if permission.authorized:
                    if verbose:
                        print authorized_style("authorized")
                    return True
                else:
                    break

        return permission_type.permission_not_found(self,
                                                    verbose=verbose,
                                                    **context)

    def require_permission(self, permission_type, verbose=None, **context):
        """Asserts the user has permission to perform an action.

        This method is similar to L{has_permission}, but instead of returning a
        boolean value, it will raise an exception if the permission is not
        granted.

        @param permission_type: The kind of permission to assert.
        @type permission_type: L{Permission} subclass

        @param verbose: A boolean flag that enables or disables on screen
            reporting of the checks executed by this method. Can help debugging
            authorization issues. When set, overrides the value of the module
            L{verbose} flag.
        @type verbose: bool

        @param context: Keyword parameters to supply to each tested permission.
            Each parameter will be forwarded to the permission's
            L{match<woost.models.permission.Permission.match>} method. Each
            subclass or L{Permission<woost.models.permission.Permission>}
            can define its set of required parameters, and all of its
            subclasses must implement exactly that set.

        @raise L{AuthorizationError}: Raised if the user doesn't have the
            specified permission.
        """
        if not self.has_permission(permission_type, verbose=verbose, **
                                   context):
            raise AuthorizationError(user=self,
                                     permission_type=permission_type,
                                     context=context)
Ejemplo n.º 26
0
class Feed(Publishable):

    type_group = "setup"
    instantiable = True

    groups_order = ["meta", "feed_items"]

    members_order = [
        "title", "ttl", "image", "description", "limit", "query_parameters",
        "item_title_expression", "item_link_expression",
        "item_publication_date_expression", "item_description_expression"
    ]

    default_mime_type = u"application/rss+xml"

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(qname="woost.feed_controller"))

    edit_controller = \
        "woost.controllers.backoffice.feedfieldscontroller." \
        "FeedFieldsController"
    edit_view = "woost.views.FeedFields"

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          member_group="meta")

    ttl = schema.Integer(listed_by_default=False, member_group="meta")

    image = schema.Reference(
        type=Publishable,
        related_end=schema.Collection(),
        relation_constraints=Publishable.resource_type.equal("image"),
        member_group="meta")

    description = schema.String(required=True,
                                translated=True,
                                listed_by_default=False,
                                edit_control="cocktail.html.TextArea",
                                member_group="meta")

    limit = schema.Integer(min=1,
                           listed_by_default=False,
                           member_group="feed_items")

    query_parameters = schema.Mapping(keys=schema.String(),
                                      required=True,
                                      listed_by_default=False,
                                      member_group="feed_items")

    item_title_expression = schema.CodeBlock(language="python",
                                             required=True,
                                             default="translations(item)",
                                             member_group="feed_items")

    item_link_expression = schema.CodeBlock(language="python",
                                            required=True,
                                            default="cms.uri(item)",
                                            member_group="feed_items")

    item_publication_date_expression = schema.CodeBlock(
        language="python",
        required=True,
        default="item.start_date or item.creation_time",
        member_group="feed_items")

    item_description_expression = schema.CodeBlock(language="python",
                                                   required=True,
                                                   default="item.description",
                                                   member_group="feed_items")

    def select_items(self):

        user_collection = UserCollection(Publishable)
        user_collection.allow_paging = False
        user_collection.allow_member_selection = False
        user_collection.allow_language_selection = False
        user_collection.params.source = self.query_parameters.get
        user_collection.available_languages = \
            Configuration.instance.get_enabled_languages()
        items = user_collection.subset

        if self.limit:
            items.range = (0, self.limit)

        return items
Ejemplo n.º 27
0
class ShopOrder(Item):

    members_order = [
        "address", "town", "region", "country", "postal_code", "cost",
        "entries"
    ]

    address = schema.String(member_group="shipping_info",
                            required=True,
                            listed_by_default=False)

    town = schema.String(member_group="shipping_info",
                         required=True,
                         listed_by_default=False)

    region = schema.String(member_group="shipping_info",
                           required=True,
                           listed_by_default=False)

    country = schema.Reference(
        member_group="shipping_info",
        type=Country,
        related_end=schema.Collection(),
        required=True,
        listed_by_default=False,
        user_filter="cocktail.controllers.userfilter.MultipleChoiceFilter")

    postal_code = schema.String(member_group="shipping_info",
                                required=True,
                                listed_by_default=False)

    cost = schema.Decimal(required=True, default=Decimal("0"), editable=False)

    language = schema.String(
        required=True,
        format="^[a-z]{2}$",
        editable=False,
        default=schema.DynamicDefault(get_language),
        text_search=False,
        translate_value=lambda value, language=None, **kwargs: u""
        if not value else translations(value, language, **kwargs))

    status = schema.String(
        required=True,
        indexed=True,
        enumeration=["pending", "accepted", "failed"],
        default="pending",
        text_search=False,
        translate_value=lambda value, language=None, **kwargs: u""
        if not value else translations(
            "woost.extensions.shop.ShopOrder.status " + value, language, **
            kwargs))

    entries = schema.Collection(
        items="woost.extensions.shop.shoporderentry.ShopOrderEntry",
        integral=True,
        bidirectional=True,
        min=1)

    def calculate_cost(self,
                       include_shipping=True,
                       include_taxes=True,
                       include_discounts=True):
        """Calculates the costs for the order.
        @rtype: dict
        """
        costs = {
            "pricing_policies": [],
            "price": {
                "cost": 0,
                "percentage": 0,
                "total": None
            },
            "shipping":
            0,
            "tax": {
                "cost": 0,
                "percentage": 0
            },
            "entries": [{
                "pricing_policies": [],
                "quantity": entry.quantity,
                "paid_quantity": entry.quantity,
                "price": {
                    "cost": entry.product.price,
                    "percentage": 0
                },
                "shipping": 0,
                "tax": {
                    "cost": 0,
                    "percentage": 0
                }
            } for entry in self.entries]
        }

        from woost.extensions.shop import ShopExtension
        shop_ext = ShopExtension.instance

        policies = list()

        if include_discounts:
            policies.extend(shop_ext.discounts)

        if include_shipping:
            policies.extend(shop_ext.shipping_costs)

        if include_taxes:
            policies.extend(shop_ext.taxes)

        for pricing_policy in policies:
            matching_items = pricing_policy.select_matching_items()

            if issubclass(matching_items.type, ShopOrder):
                if pricing_policy.applies_to(self):
                    pricing_policy.apply(self, costs)
                    costs["pricing_policies"].append(pricing_policy)
            else:
                for entry, entry_costs in zip(self.entries, costs["entries"]):
                    if pricing_policy.applies_to(entry.product):
                        pricing_policy.apply(entry.product, entry_costs)
                        entry_costs["pricing_policies"].append(pricing_policy)

        # Total price
        def apply_percentage(costs):
            cost = costs["cost"]
            percentage = costs["percentage"]
            if percentage:
                cost += cost * percentage / 100
            costs["total"] = cost
            return cost

        total_price = apply_percentage(costs["price"])

        for entry_costs in costs["entries"]:
            entry_price = apply_percentage(entry_costs["price"])
            entry_total_price = entry_price * entry_costs["paid_quantity"]
            entry_costs["total_price"] = entry_total_price
            total_price += entry_total_price

        costs["total_price"] = total_price

        # Total taxes
        total_taxes = costs["tax"]["cost"] \
                    + total_price * costs["tax"]["percentage"] / 100

        for entry_costs in costs["entries"]:
            quantity = entry_costs["paid_quantity"]
            entry_price = entry_costs["price"]["total"] * quantity
            entry_taxes = entry_costs["tax"]["cost"] * quantity \
                        + entry_price * entry_costs["tax"]["percentage"] / 100
            total_taxes += entry_taxes
            entry_costs["tax"]["total"] = entry_taxes

        costs["total_taxes"] = total_taxes

        # Total shipping costs
        total_shipping_costs = costs["shipping"] \
                             + sum(entry_costs["shipping"] * entry_costs["quantity"]
                                   for entry_costs in costs["entries"])
        costs["total_shipping_costs"] = total_shipping_costs

        # Grand total
        costs["total"] = total_price + total_taxes + total_shipping_costs

        return costs

    def count_items(self):
        """Gets the number of purchased product units in the order.
        @rtype: int
        """
        return sum(entry.quantity for entry in self.entries)

    def get_product_entry(self, product):
        """Gets the entry in the order for the given product.

        @param product: The product to obtain the entry for.
        @type product: L{Product<woost.extensions.shop.product.Product>}

        @return: The matching entry, or None if the order doesn't contain an
            entry for the indicated product.
        @rtype: L{ShopOrderEntry
                  <woost.extensions.shop.shoporderentry.ShopOrderEntry>}
        """
        for entry in self.entries:
            if entry.product is product:
                return entry

    def set_product_quantity(self, product, quantity):
        """Updates the quantity of ordered units for the indicated product.

        If an entry for the given product already exists, its quantity will be
        updated to the indicated value. If the indicated quantity is zero, the
        entry will be removed from the order. If no matching entry exists, a
        new entry for the product will be created with the specified amount of
        units.

        @param product: The product to set the quantity for.
        @type product: L{Product<woost.extensions.shop.product.Product>}

        @param quantity: The number of units of the product to order.
        @type quantity: int
        """
        entry = self.get_product_entry(product)

        if entry is None:
            if quantity:
                entry = ShopOrderEntry(product=product, quantity=quantity)
                self.entries.append(entry)
                if self.is_inserted:
                    entry.insert()
        else:
            if quantity:
                entry.quantity = quantity
            else:
                if entry.is_inserted:
                    entry.delete()
                else:
                    self.entries.remove(entry)
Ejemplo n.º 28
0
class ECommerceProduct(Publishable):

    instantiable = False

    members_order = [
        "description",
        "price",
        "weight",
        "attachments",
        "purchase_model",
        "purchases",
        "template"
    ]

    default_controller = schema.DynamicDefault(
        lambda: Controller.get_instance(
            qname = "woost.extensions.ecommerce.product_controller"
        )
    )

    description = schema.String(
        translated = True,
        edit_control = "woost.views.RichTextEditor",
        member_group = "product_data"
    )

    price = schema.Decimal(
        required = True,
        default = Decimal("0"),
        member_group = "product_data"
    )
 
    weight = schema.Decimal(
        translate_value = lambda value, language = None, **kwargs:
            "" if not value else "%s Kg" % translations(value, language),
        member_group = "product_data"
    )

    attachments = schema.Collection(
        items = schema.Reference(type = File),
        related_end = schema.Collection(),
        member_group = "product_data"
    )

    purchase_model = schema.Reference(
        class_family = "woost.extensions.ecommerce.ecommercepurchase."
                       "ECommercePurchase",
        default = schema.DynamicDefault(
            lambda: ECommerceProduct.purchase_model.class_family
        ),
        required = True,
        searchable = False,
        member_group = "product_data"
    )

    purchases = schema.Collection(
        items = "woost.extensions.ecommerce.ecommercepurchase."
                "ECommercePurchase",
        bidirectional = True,
        visible = False,
        member_group = "product_data"
    )

    template = schema.Reference(
        type = Template,
        related_end = schema.Collection(),
        default = schema.DynamicDefault(
            lambda: Template.get_instance(
                qname = "woost.extensions.ecommerce.product_template"
            )
        ),
        member_group = "presentation"
    )

    def get_image(self):
        for attachment in self.attachments:
            if attachment.resource_type == "image" \
            and attachment.is_accessible():
                return attachment

    def offers(self):
        from woost.extensions.ecommerce import ECommerceExtension
        for pricing in ECommerceExtension.instance.pricing:
            if not pricing.hidden and pricing.applies_to(self):
                yield pricing

    @getter
    def inherited_resources(self):

        if self.inherit_resources and self.parent is None:
            catalog = Document.get_instance(
                qname = "woost.extensions.ecommerce.catalog_page"
            )

            if catalog:
                for resource in catalog.inherited_resources:
                    yield resource

                for resource in catalog.branch_resources:
                    yield resource        
        else:
            for resource in Publishable.inherited_resources.__get__(self):
                yield resource
Ejemplo n.º 29
0
class IssuuDocument(Publishable):

    instantiable = True
    default_per_language_publication = True
    type_group = "resource"

    default_controller = schema.DynamicDefault(lambda: Controller.get_instance(
        qname="woost.issuu_document_controller"))

    members_order = ["title", "issuu_document_url", "thumbnail_page"]

    title = schema.String(indexed=True,
                          normalized_index=True,
                          full_text_indexed=True,
                          descriptive=True,
                          translated=True,
                          required=True,
                          member_group="content")

    issuu_document_url = schema.URL(required=True,
                                    format=ISSUU_DOCUMENT_URL_PATTERN,
                                    searchable=False,
                                    member_group="content")

    thumbnail_page = schema.Integer(required=True,
                                    default=1,
                                    min=1,
                                    member_group="content",
                                    listed_by_default=False)

    issuu_document_id = schema.String(editable=False,
                                      unique=True,
                                      indexed=True,
                                      searchable=False,
                                      member_group="content",
                                      listed_by_default=False)

    issuu_config_id = schema.String(editable=False,
                                    searchable=False,
                                    member_group="content",
                                    listed_by_default=False)

    def get_issuu_uri(self, page_number=None):
        if page_number == None:
            page_number = self.thumbnail_page

        return u"http://issuu.com/%s/docs/%s/%s?e=%s" % (
            self.issuu_document_username, self.issuu_document_name,
            page_number, self.issuu_config_id)

    def get_uri(self,
                path=None,
                parameters=None,
                language=None,
                host=None,
                encode=True):

        uri = self.get_issuu_uri()

        if uri is not None:

            if path:
                uri = make_uri(uri, *path)

            if parameters:
                uri = make_uri(uri, **parameters)

            uri = self._fix_uri(uri, host, encode)

        return uri

    @event_handler
    def handle_changed(cls, event):

        item = event.source
        member = event.member

        if member.name == "issuu_document_url":
            item._update_issuu_document_metadata()

    def _update_issuu_document_metadata(self, timeout=5):
        if self.issuu_document_url:
            metadata = extract_issuu_document_metadata(self.issuu_document_url)
            self.issuu_document_username = metadata.get("username")
            self.issuu_document_name = metadata.get("docname")
            self.issuu_config_id = metadata.get("configid")

            if self.issuu_document_username and self.issuu_document_name:
                response = urlopen(
                    "http://search.issuu.com/api/2_0/document?q=docname:%s&username=%s"
                    % (self.issuu_document_name, self.issuu_document_username),
                    timeout=timeout)
                status = response.getcode()
                body = response.read()
                if status < 200 or status > 299:
                    raise IssuuSearchAPIError(body)

                data = loads(body)
                try:
                    self.issuu_document_id = \
                        data["response"]["docs"][0]["documentId"]
                except (KeyError, IndexError):
                    self.issuu_document_id = None

            if self.issuu_config_id is None:
                url = Location(self.issuu_document_url)
                url.query_string.update(e=0)
                response = urlopen(url.get_url(), timeout=timeout)
                status = response.getcode()
                body = response.read()
                if status >= 200 and status <= 299:
                    url = Location(response.geturl())
                    issuu_config_id = url.query_string.get("e")
                    if issuu_config_id:
                        self.issuu_config_id = issuu_config_id[0]
Ejemplo n.º 30
0
Publishable.members_order += ["open_graph_enabled", "open_graph_type"]

Publishable.add_member(
    schema.Boolean("open_graph_enabled",
                   required=True,
                   default=True,
                   listed_by_default=False,
                   member_group="meta.open_graph"))

Publishable.add_member(
    schema.Reference("open_graph_type",
                     type=OpenGraphType,
                     required=Publishable["open_graph_enabled"],
                     related_end=schema.Collection(block_delete=True),
                     default=schema.DynamicDefault(
                         lambda: OpenGraphType.get_instance(code="article")),
                     indexed=True,
                     listed_by_default=False,
                     member_group="meta.open_graph",
                     edit_control=display_factory(
                         "cocktail.html.DropdownSelector",
                         grouping=lambda type: type.category)))


def _get_publishable_properties(self):

    properties = {
        "og:title": translations(self),
        "og:type": self.open_graph_type.code,
        "og:url": self.get_uri(host=".")
    }