Пример #1
0
    def test_raise_exception_by_mocking_collision(self):
        thread_id = feedback_services.create_thread('exploration', '0',
                                                    'test_author', 'subject 1',
                                                    'text 1')
        # Simulating the _generate_id function in the
        # GeneralFeedbackMessageModel class.
        instance_id = '.'.join([thread_id, '0'])

        expected_exception_regexp = (
            r'The following feedback message ID\(s\) conflicted on '
            'create: %s' % (instance_id))
        with self.assertRaisesRegexp(Exception, expected_exception_regexp):
            feedback_models.GeneralFeedbackMessageModel.create(
                feedback_domain.FullyQualifiedMessageIdentifier(
                    thread_id, '0'))
Пример #2
0
def create_messages(thread_ids,
                    author_id,
                    updated_status,
                    updated_subject,
                    text,
                    received_via_email=False):
    """Creates a new message for each of the distinct threads in thread_ids and
    for each message, subscribes the author to the thread.

    Args:
        thread_ids: list(str). The thread ids to append the messages to.
        author_id: str. The id of the author who creates the messages.
        updated_status: str. One of STATUS_CHOICES. Applied to each thread.
            Must be supplied if this is the first message of the threads.
            Otherwise, this property should only exist when the status
            changes.
        updated_subject: str. New thread subject. Applied to each thread. Must
            be supplied if this is the first message of the threads. Otherwise,
            this property should only exist when the subject changes.
        text: str. The text of the feedback message. This may be ''.
        received_via_email: bool. Whether the new message(s) are received via
            email or web.

    Returns:
        list(FeedbackMessage). The domain objects representing the new messages
        added in the datastore.

    Raises:
        Exception. Thread_ids must be distinct.
        Exception. One or more GeneralFeedbackThreadModel entities not found.
    """
    from core.domain import event_services

    # Check that the thread_ids are distinct.
    if len(set(thread_ids)) != len(thread_ids):
        raise Exception(
            'Thread ids must be distinct when calling create_messsages.')

    # Get the threads at the outset, in order to check that there are models
    # corresponding to each of the thread_ids.
    thread_models = feedback_models.GeneralFeedbackThreadModel.get_multi(
        thread_ids)
    thread_ids_that_do_not_have_models = []
    for index, thread_model in enumerate(thread_models):
        if thread_model is None:
            thread_ids_that_do_not_have_models.append(thread_ids[index])
    if len(thread_ids_that_do_not_have_models) > 0:
        multiple_thread_models_are_missing = (
            len(thread_ids_that_do_not_have_models) > 1)
        raise Exception(
            'Thread%s belonging to the GeneralFeedbackThreadModel class with '
            'id%s:[%s] %s not found.' %
            ('s' if multiple_thread_models_are_missing else '',
             's' if multiple_thread_models_are_missing else '',
             ' '.join(thread_ids_that_do_not_have_models),
             'were' if multiple_thread_models_are_missing else 'was'))

    # Get the corresponding message ids, which are required for message
    # creation.
    message_ids = (feedback_models.GeneralFeedbackMessageModel.
                   get_message_counts(thread_ids))

    # Create a list of FullyQualifiedMessageIdentifier objects so that each
    # (thread_id, message_id) pair is kept together.
    message_identifiers = []
    for thread_id, message_id in python_utils.ZIP(thread_ids, message_ids):
        message_identifiers.append(
            feedback_domain.FullyQualifiedMessageIdentifier(
                thread_id, message_id))

    # Create the GeneralFeedbackMessageModel instances.
    message_models = feedback_models.GeneralFeedbackMessageModel.create_multi(
        message_identifiers)

    # Update the message instances.
    for index, message_model in enumerate(message_models):
        message_model.thread_id = thread_ids[index]
        message_model.message_id = message_ids[index]
        message_model.author_id = author_id
        message_model.text = text
        message_model.received_via_email = received_via_email
        # Get the corresponding thread in storage.
        thread_model = thread_models[index]
        if updated_status:
            message_model.updated_status = updated_status
            if message_model.message_id == 0:
                # New thread.
                if thread_model.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                    event_services.FeedbackThreadCreatedEventHandler.record(
                        thread_model.entity_id)
            else:
                # Thread status changed.
                if thread_model.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                    (event_services.FeedbackThreadStatusChangedEventHandler.
                     record(thread_model.entity_id, thread_model.status,
                            updated_status))
        if updated_subject:
            message_model.updated_subject = updated_subject
    feedback_models.GeneralFeedbackMessageModel.put_multi(message_models)

    # Update the message data cache of the threads.
    for thread_model in thread_models:
        thread_model.message_count += 1
        if text:
            thread_model.last_nonempty_message_text = text
            thread_model.last_nonempty_message_author_id = author_id

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the threads reflects the last time a message was
    # added to it.
    old_statuses = [thread_model.status for thread_model in thread_models]
    new_statuses = old_statuses
    if updated_status or updated_subject:
        new_statuses = []
        for index, thread_model in enumerate(thread_models):
            # Can't be the first thread.
            if message_ids[index] != 0:
                if updated_status and (updated_status != thread_model.status):
                    thread_model.status = updated_status
                if updated_subject and (updated_subject !=
                                        thread_model.subject):
                    thread_model.subject = updated_subject
            new_statuses.append(thread_model.status)
    feedback_models.GeneralFeedbackThreadModel.put_multi(thread_models)

    # For each thread, we do a put on the suggestion linked (if it exists) to
    # the thread, so that the last_updated time changes to show that there is
    # activity in the thread.
    thread_ids_that_have_linked_suggestions = []
    for thread_model in thread_models:
        if thread_model.has_suggestion:
            thread_ids_that_have_linked_suggestions.append(thread_model.id)
    general_suggestion_models = (
        suggestion_models.GeneralSuggestionModel.get_multi(
            thread_ids_that_have_linked_suggestions))
    suggestion_models_to_update = []
    for suggestion_model in general_suggestion_models:
        # As the thread is created before the suggestion, for the first message
        # we need not update the suggestion.
        if suggestion_model:
            suggestion_models_to_update.append(suggestion_model)
    suggestion_models.GeneralSuggestionModel.put_multi(
        suggestion_models_to_update)

    if (feconf.CAN_SEND_EMAILS
            and (feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS
                 and user_services.is_user_registered(author_id))):
        for index, thread_model in enumerate(thread_models):
            _add_message_to_email_buffer(author_id,
                                         thread_model.id, message_ids[index],
                                         len(text), old_statuses[index],
                                         new_statuses[index])

    if author_id:
        subscription_services.subscribe_to_threads(author_id, thread_ids)
        add_message_ids_to_read_by_list(author_id, message_identifiers)

    # Convert the GeneralFeedbackMessageModels into a list of FeedbackMessage
    # domain objects.
    feedback_messages = [
        _get_message_from_model(message_model)
        for message_model in message_models
    ]

    return feedback_messages