Esempio n. 1
0
 /**
  * Enter description here...
  *
  * @param CerberusParserMessage $message
  * @return integer
  */
 public static function parseMessage(CerberusParserMessage $message, $options = array())
 {
     /*
      * options:
      * 'no_autoreply'
      */
     $logger = DevblocksPlatform::getConsoleLog();
     $settings = DevblocksPlatform::getPluginSettingsService();
     $helpdesk_senders = CerberusApplication::getHelpdeskSenders();
     // Pre-parse mail filters
     $pre_filters = Model_PreParseRule::getMatches($message);
     if (is_array($pre_filters) && !empty($pre_filters)) {
         // Load filter action manifests for reuse
         $ext_action_mfts = DevblocksPlatform::getExtensions('cerberusweb.mail_filter.action', false);
         // Loop through all matching filters
         foreach ($pre_filters as $pre_filter) {
             // Do something with matching filter's actions
             foreach ($pre_filter->actions as $action_key => $action) {
                 switch ($action_key) {
                     case 'blackhole':
                         return NULL;
                         break;
                     case 'redirect':
                         @($to = $action['to']);
                         CerberusMail::reflect($message, $to);
                         return NULL;
                         break;
                     case 'bounce':
                         @($msg = $action['message']);
                         @($subject = 'Delivery failed: ' . self::fixQuotePrintableString($message->headers['subject']));
                         // [TODO] Follow the RFC spec on a true bounce
                         if (null != ($fromAddressInst = CerberusParser::getAddressFromHeaders($message->headers))) {
                             CerberusMail::quickSend($fromAddressInst->email, $subject, $msg);
                         }
                         return NULL;
                         break;
                     default:
                         // Plugin pre-parser filter actions
                         if (isset($ext_action_mfts[$action_key])) {
                             if (null != @($ext_action = $ext_action_mfts[$action_key]->createInstance())) {
                                 try {
                                     /* @var $ext_action Extension_MailFilterAction */
                                     $ext_action->run($pre_filter, $message);
                                 } catch (Exception $e) {
                                 }
                             }
                         }
                         break;
                 }
             }
         }
     }
     $headers =& $message->headers;
     // From
     if (null == ($fromAddressInst = CerberusParser::getAddressFromHeaders($headers))) {
         $logger->err("[Parser] 'From' address could not be created.");
         return NULL;
     }
     // To/Cc/Bcc
     $to = array();
     $sTo = @$headers['to'];
     $bIsNew = true;
     if (!empty($sTo)) {
         // [TODO] Do we still need this RFC address parser?
         $to = CerberusParser::parseRfcAddress($sTo);
     }
     // Subject
     // Fix quote printable subject (quoted blocks can appear anywhere in subject)
     $sSubject = "";
     if (isset($headers['subject']) && !empty($headers['subject'])) {
         $sSubject = $headers['subject'];
         if (is_array($sSubject)) {
             $sSubject = array_shift($sSubject);
         }
     }
     // The subject can still end up empty after QP decode
     if (empty($sSubject)) {
         $sSubject = "(no subject)";
     }
     // Date
     $iDate = @strtotime($headers['date']);
     // If blank, or in the future, set to the current date
     if (empty($iDate) || $iDate > time()) {
         $iDate = time();
     }
     // Is banned?
     if (1 == $fromAddressInst->is_banned) {
         $logger->info("[Parser] Ignoring ticket from banned address: " . $fromAddressInst->email);
         return NULL;
     }
     // Overloadable
     $enumSpamTraining = '';
     // Message Id / References / In-Reply-To
     @($sMessageId = $headers['message-id']);
     $body_append_text = array();
     $body_append_html = array();
     // [mdf]Check attached files before creating the ticket because we may need to overwrite the message-id
     // also store any contents of rfc822 files so we can include them after the body
     foreach ($message->files as $filename => $file) {
         /* @var $file ParserFile */
         switch ($file->mime_type) {
             case 'message/rfc822':
                 $full_filename = $file->tmpname;
                 $mail = mailparse_msg_parse_file($full_filename);
                 $struct = mailparse_msg_get_structure($mail);
                 $msginfo = mailparse_msg_get_part_data($mail);
                 $inline_headers = $msginfo['headers'];
                 if (isset($headers['from']) && (strtolower(substr($headers['from'], 0, 11)) == 'postmaster@' || strtolower(substr($headers['from'], 0, 14)) == 'mailer-daemon@')) {
                     $headers['in-reply-to'] = $inline_headers['message-id'];
                 }
                 break;
         }
     }
     // [JAS] [TODO] References header may contain multiple message-ids to find
     if (null != ($ids = self::findParentMessage($headers))) {
         $bIsNew = false;
         $id = $ids['ticket_id'];
         $msgid = $ids['message_id'];
         // Is it a worker reply from an external client?  If so, proxy
         if (null != ($worker_address = DAO_AddressToWorker::getByAddress($fromAddressInst->email))) {
             $logger->info("[Parser] Handling an external worker response from " . $fromAddressInst->email);
             if (!DAO_Ticket::isTicketRequester($worker_address->address, $id)) {
                 // Watcher Commands [TODO] Document on wiki/etc
                 if (0 != ($matches = preg_match_all("/\\[(.*?)\\]/i", $message->headers['subject'], $commands))) {
                     @($command = strtolower(array_pop($commands[1])));
                     $logger->info("[Parser] Worker command: " . $command);
                     switch ($command) {
                         case 'close':
                             DAO_Ticket::updateTicket($id, array(DAO_Ticket::IS_CLOSED => CerberusTicketStatus::CLOSED));
                             break;
                         case 'take':
                             DAO_Ticket::updateTicket($id, array(DAO_Ticket::NEXT_WORKER_ID => $worker_address->worker_id));
                             break;
                         case 'comment':
                             $comment_id = DAO_TicketComment::create(array(DAO_TicketComment::ADDRESS_ID => $fromAddressInst->id, DAO_TicketComment::CREATED => time(), DAO_TicketComment::TICKET_ID => $id, DAO_TicketComment::COMMENT => $message->body));
                             return $id;
                             break;
                         default:
                             // Typo?
                             break;
                     }
                 }
                 $attachment_files = array();
                 $attachment_files['name'] = array();
                 $attachment_files['type'] = array();
                 $attachment_files['tmp_name'] = array();
                 $attachment_files['size'] = array();
                 $i = 0;
                 foreach ($message->files as $filename => $file) {
                     $attachment_files['name'][$i] = $filename;
                     $attachment_files['type'][$i] = $file->mime_type;
                     $attachment_files['tmp_name'][$i] = $file->tmpname;
                     $attachment_files['size'][$i] = $file->file_size;
                     $i++;
                 }
                 CerberusMail::sendTicketMessage(array('message_id' => $msgid, 'content' => $message->body, 'files' => $attachment_files, 'agent_id' => $worker_address->worker_id));
                 return $id;
             } else {
                 // ... worker is a requester, treat as normal
                 $logger->info("[Parser] The external worker was a ticket requester, so we're not treating them as a watcher.");
             }
         } else {
             // Reply: Not sent by a worker
             /*
              * [TODO] check that this sender is a requester on the matched ticket
              * Otherwise blank out the $id
              */
         }
     }
     $group_id = 0;
     if (empty($id)) {
         // New Ticket
         $sMask = CerberusApplication::generateTicketMask();
         $groups = DAO_Group::getAll();
         // Routing new tickets
         if (null != ($routing_rules = Model_MailToGroupRule::getMatches($fromAddressInst, $message))) {
             if (is_array($routing_rules)) {
                 foreach ($routing_rules as $rule) {
                     // Only end up with the last 'move' action (ignore the previous)
                     if (isset($rule->actions['move'])) {
                         $group_id = intval($rule->actions['move']['group_id']);
                         // We don't need to move again when running rule actions
                         unset($rule->actions['move']);
                     }
                 }
             }
         }
         // Make sure the group exists
         if (!isset($groups[$group_id])) {
             $group_id = null;
         }
         // Last ditch effort to check for a default group to deliver to
         if (empty($group_id)) {
             if (null != ($default_team = DAO_Group::getDefaultGroup())) {
                 $group_id = $default_team->id;
             } else {
                 // Bounce
                 return null;
             }
         }
         // [JAS] It's important to not set the group_id on the ticket until the messages exist
         // or inbox filters will just abort.
         $fields = array(DAO_Ticket::MASK => $sMask, DAO_Ticket::SUBJECT => $sSubject, DAO_Ticket::IS_CLOSED => 0, DAO_Ticket::FIRST_WROTE_ID => intval($fromAddressInst->id), DAO_Ticket::LAST_WROTE_ID => intval($fromAddressInst->id), DAO_Ticket::CREATED_DATE => $iDate, DAO_Ticket::UPDATED_DATE => $iDate, DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_OPENED);
         $id = DAO_Ticket::createTicket($fields);
         // Apply routing actions to our new ticket ID
         if (isset($routing_rules) && is_array($routing_rules)) {
             foreach ($routing_rules as $rule) {
                 $rule->run($id);
             }
         }
     }
     // [JAS]: Add requesters to the ticket
     if (!empty($fromAddressInst->id) && !empty($id)) {
         // Don't add a requester if the sender is a helpdesk address
         if (isset($helpdesk_senders[$fromAddressInst->email])) {
             $logger->info("[Parser] Not adding ourselves as a requester: " . $fromAddressInst->email);
         } else {
             DAO_Ticket::createRequester($fromAddressInst->id, $id);
         }
     }
     // Add the other TO/CC addresses to the ticket
     // [TODO] This should be cleaned up and optimized
     if ($settings->get('cerberusweb.core', CerberusSettings::PARSER_AUTO_REQ, 0)) {
         @($autoreq_exclude_list = $settings->get('cerberusweb.core', CerberusSettings::PARSER_AUTO_REQ_EXCLUDE, ''));
         $destinations = self::getDestinations($headers);
         if (is_array($destinations) && !empty($destinations)) {
             // Filter out any excluded requesters
             if (!empty($autoreq_exclude_list)) {
                 @($autoreq_exclude = DevblocksPlatform::parseCrlfString($autoreq_exclude_list));
                 if (is_array($autoreq_exclude) && !empty($autoreq_exclude)) {
                     foreach ($autoreq_exclude as $excl_pattern) {
                         $excl_regexp = DevblocksPlatform::parseStringAsRegExp($excl_pattern);
                         // Check all destinations for this pattern
                         foreach ($destinations as $idx => $dest) {
                             if (@preg_match($excl_regexp, $dest)) {
                                 unset($destinations[$idx]);
                             }
                         }
                     }
                 }
             }
             foreach ($destinations as $dest) {
                 if (null != ($destInst = CerberusApplication::hashLookupAddress($dest, true))) {
                     // Skip if the destination is one of our senders or the matching TO
                     if (isset($helpdesk_senders[$destInst->email])) {
                         continue;
                     }
                     DAO_Ticket::createRequester($destInst->id, $id);
                 }
             }
         }
     }
     $attachment_path = APP_STORAGE_PATH . '/attachments/';
     // [TODO] This should allow external attachments (S3)
     $fields = array(DAO_Message::TICKET_ID => $id, DAO_Message::CREATED_DATE => $iDate, DAO_Message::ADDRESS_ID => $fromAddressInst->id);
     $email_id = DAO_Message::create($fields);
     // Content
     DAO_MessageContent::create($email_id, $message->body);
     // Headers
     foreach ($headers as $hk => $hv) {
         DAO_MessageHeader::create($email_id, $hk, $hv);
     }
     // [mdf] Loop through files to insert attachment records in the db, and move temporary files
     if (!empty($email_id)) {
         foreach ($message->files as $filename => $file) {
             /* @var $file ParserFile */
             //[mdf] skip rfc822 messages since we extracted their content above
             if ($file->mime_type == 'message/rfc822') {
                 continue;
             }
             $fields = array(DAO_Attachment::MESSAGE_ID => $email_id, DAO_Attachment::DISPLAY_NAME => $filename, DAO_Attachment::MIME_TYPE => $file->mime_type, DAO_Attachment::FILE_SIZE => intval($file->file_size));
             $file_id = DAO_Attachment::create($fields);
             if (empty($file_id)) {
                 @unlink($file->tmpname);
                 // remove our temp file
                 continue;
             }
             // Make file attachments use buckets so we have a max per directory
             $attachment_bucket = sprintf("%03d/", mt_rand(1, 100));
             $attachment_file = $file_id;
             if (!file_exists($attachment_path . $attachment_bucket)) {
                 @mkdir($attachment_path . $attachment_bucket, 0770, true);
                 // [TODO] Needs error checking
             }
             rename($file->getTempFile(), $attachment_path . $attachment_bucket . $attachment_file);
             // [TODO] Split off attachments into its own DAO
             DAO_Attachment::update($file_id, array(DAO_Attachment::FILEPATH => $attachment_bucket . $attachment_file));
         }
     }
     // Pre-load custom fields
     if (isset($message->custom_fields) && !empty($message->custom_fields)) {
         foreach ($message->custom_fields as $cf_id => $cf_val) {
             if (is_array($cf_val) && !empty($cf_val) || !is_array($cf_val) && 0 != strlen($cf_val)) {
                 DAO_CustomFieldValue::setFieldValue('cerberusweb.fields.source.ticket', $id, $cf_id, $cf_val);
             }
         }
     }
     // Finalize our new ticket details (post-message creation)
     if ($bIsNew && !empty($id) && !empty($email_id)) {
         // First thread (needed for anti-spam)
         DAO_Ticket::updateTicket($id, array(DAO_Ticket::FIRST_MESSAGE_ID => $email_id));
         // Prime the change fields (which a few things like anti-spam might change before we commit)
         $change_fields = array(DAO_Ticket::TEAM_ID => $group_id);
         $out = CerberusBayes::calculateTicketSpamProbability($id);
         if (!empty($group_id)) {
             @($spam_threshold = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_THRESHOLD, 80));
             @($spam_action = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_ACTION, ''));
             @($spam_action_param = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_ACTION_PARAM, ''));
             if ($out['probability'] * 100 >= $spam_threshold) {
                 $enumSpamTraining = CerberusTicketSpamTraining::SPAM;
                 switch ($spam_action) {
                     default:
                     case 0:
                         // do nothing
                         break;
                     case 1:
                         // delete
                         $change_fields[DAO_Ticket::IS_CLOSED] = 1;
                         $change_fields[DAO_Ticket::IS_DELETED] = 1;
                         break;
                     case 2:
                         // move
                         $buckets = DAO_Bucket::getAll();
                         // Verify bucket exists
                         if (!empty($spam_action_param) && isset($buckets[$spam_action_param])) {
                             $change_fields[DAO_Ticket::TEAM_ID] = $group_id;
                             $change_fields[DAO_Ticket::CATEGORY_ID] = $spam_action_param;
                         }
                         break;
                 }
             }
         }
         // end spam training
         // Save properties
         if (!empty($change_fields)) {
             DAO_Ticket::updateTicket($id, $change_fields);
         }
     }
     // Reply notifications (new messages are handled by 'move' listener)
     if (!$bIsNew) {
         // Inbound Reply Event
         $eventMgr = DevblocksPlatform::getEventService();
         $eventMgr->trigger(new Model_DevblocksEvent('ticket.reply.inbound', array('ticket_id' => $id)));
     }
     // New ticket processing
     if ($bIsNew) {
         // Auto reply
         @($autoreply_enabled = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_AUTO_REPLY_ENABLED, 0));
         @($autoreply = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_AUTO_REPLY, ''));
         /*
          * Send the group's autoreply if one exists, as long as this ticket isn't spam
          */
         if (!isset($options['no_autoreply']) && $autoreply_enabled && !empty($autoreply) && $enumSpamTraining != CerberusTicketSpamTraining::SPAM) {
             CerberusMail::sendTicketMessage(array('ticket_id' => $id, 'message_id' => $email_id, 'content' => str_replace(array('#ticket_id#', '#mask#', '#subject#', '#timestamp#', '#sender#', '#sender_first#', '#orig_body#'), array($id, $sMask, $sSubject, date('r'), $fromAddressInst->email, $fromAddressInst->first_name, ltrim($message->body)), $autoreply), 'is_autoreply' => true, 'dont_keep_copy' => true));
         }
     }
     // end bIsNew
     unset($message);
     // Re-open and update our date on new replies
     if (!$bIsNew) {
         DAO_Ticket::updateTicket($id, array(DAO_Ticket::UPDATED_DATE => time(), DAO_Ticket::IS_WAITING => 0, DAO_Ticket::IS_CLOSED => 0, DAO_Ticket::IS_DELETED => 0, DAO_Ticket::LAST_WROTE_ID => $fromAddressInst->id, DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_CUSTOMER_REPLY));
         // [TODO] The TICKET_CUSTOMER_REPLY should be sure of this message address not being a worker
     }
     @imap_errors();
     // Prevent errors from spilling out into STDOUT
     return $id;
 }
Esempio n. 2
0
 private function _handleImportComment($xml)
 {
     $mask = (string) $xml->mask;
     $author_email = (string) $xml->author_email;
     $note = trim((string) $xml->note);
     $created = intval((string) $xml->created_date);
     $author_address = CerberusApplication::hashLookupAddress($author_email, true);
     // Bad file
     if (empty($note) || empty($author_address) || empty($mask)) {
         return false;
     }
     //		echo "MASK: ",$mask,"<BR>";
     //		echo " -- Author: ",$author_address->email,"<BR>";
     //		echo " -- Note: ",$note,"<BR>";
     if (null !== ($ticket = DAO_Ticket::getTicketByMask($mask))) {
         $fields = array(DAO_TicketComment::CREATED => $created, DAO_TicketComment::TICKET_ID => $ticket->id, DAO_TicketComment::COMMENT => $note, DAO_TicketComment::ADDRESS_ID => $author_address->id);
         if (null !== ($comment_id = DAO_TicketComment::create($fields))) {
             return true;
         }
     }
     return false;
 }
Esempio n. 3
0
 function deleteCommentAction()
 {
     @($ticket_id = DevblocksPlatform::importGPC($_REQUEST['ticket_id'], 'integer', 0));
     @($comment_id = DevblocksPlatform::importGPC($_REQUEST['comment_id'], 'integer', 0));
     //		@$worker_id = CerberusApplication::getActiveWorker()->id;
     if (empty($ticket_id) || empty($comment_id)) {
         // empty($worker_id) ||
         DevblocksPlatform::redirect(new DevblocksHttpResponse(array('display', $ticket_id)));
     }
     @($active_worker = CerberusApplication::getActiveWorker());
     $comment = DAO_TicketComment::get($comment_id);
     if (!empty($active_worker) && ($active_worker->is_superuser || $comment->getAddress()->email == $active_worker->email)) {
         DAO_TicketComment::delete($comment_id);
     }
     DevblocksPlatform::redirect(new DevblocksHttpResponse(array('display', $ticket_id, 'comments')));
 }
Esempio n. 4
0
 function handleRequest(DevblocksHttpRequest $request)
 {
     $worker = CerberusApplication::getActiveWorker();
     if (empty($worker)) {
         return;
     }
     $stack = $request->path;
     array_shift($stack);
     // print
     @($object = strtolower(array_shift($stack)));
     // ticket|message|etc
     $tpl = DevblocksPlatform::getTemplateService();
     $tpl->assign('path', $this->_TPL_PATH);
     $settings = DevblocksPlatform::getPluginSettingsService();
     $tpl->assign('settings', $settings);
     $translate = DevblocksPlatform::getTranslationService();
     $tpl->assign('translate', $translate);
     $teams = DAO_Group::getAll();
     $tpl->assign('teams', $teams);
     $buckets = DAO_Bucket::getAll();
     $tpl->assign('buckets', $buckets);
     $workers = DAO_Worker::getAll();
     $tpl->assign('workers', $workers);
     // Security
     $active_worker = CerberusApplication::getActiveWorker();
     $active_worker_memberships = $active_worker->getMemberships();
     // [TODO] Make this pluggable
     // Subcontroller
     switch ($object) {
         case 'ticket':
             @($id = array_shift($stack));
             @($ticket = is_numeric($id) ? DAO_Ticket::getTicket($id) : DAO_Ticket::getTicketByMask($id));
             $convo_timeline = array();
             $messages = $ticket->getMessages();
             foreach ($messages as $message_id => $message) {
                 /* @var $message CerberusMessage */
                 $key = $message->created_date . '_m' . $message_id;
                 // build a chrono index of messages
                 $convo_timeline[$key] = array('m', $message_id);
             }
             @($mail_inline_comments = DAO_WorkerPref::get($active_worker->id, 'mail_inline_comments', 1));
             if ($mail_inline_comments) {
                 // if inline comments are enabled
                 $comments = DAO_TicketComment::getByTicketId($ticket->id);
                 arsort($comments);
                 $tpl->assign('comments', $comments);
                 // build a chrono index of comments
                 foreach ($comments as $comment_id => $comment) {
                     /* @var $comment Model_TicketComment */
                     $key = $comment->created . '_c' . $comment_id;
                     $convo_timeline[$key] = array('c', $comment_id);
                 }
             }
             ksort($convo_timeline);
             $tpl->assign('convo_timeline', $convo_timeline);
             // Comment parent addresses
             $comment_addresses = array();
             foreach ($comments as $comment) {
                 /* @var $comment Model_TicketComment */
                 $address_id = intval($comment->address_id);
                 if (!isset($comment_addresses[$address_id])) {
                     $address = DAO_Address::get($address_id);
                     $comment_addresses[$address_id] = $address;
                 }
             }
             $tpl->assign('comment_addresses', $comment_addresses);
             // Message Notes
             $notes = DAO_MessageNote::getByTicketId($ticket->id);
             $message_notes = array();
             // Index notes by message id
             if (is_array($notes)) {
                 foreach ($notes as $note) {
                     if (!isset($message_notes[$note->message_id])) {
                         $message_notes[$note->message_id] = array();
                     }
                     $message_notes[$note->message_id][$note->id] = $note;
                 }
             }
             $tpl->assign('message_notes', $message_notes);
             // Make sure we're allowed to view this ticket or message
             if (!isset($active_worker_memberships[$ticket->team_id])) {
                 echo "<H1>" . $translate->_('common.access_denied') . "</H1>";
                 return;
             }
             $tpl->assign('ticket', $ticket);
             $tpl->display('file:' . $this->_TPL_PATH . 'print/ticket.tpl');
             break;
         case 'message':
             @($id = array_shift($stack));
             @($message = DAO_Ticket::getMessage($id));
             @($ticket = DAO_Ticket::getTicket($message->ticket_id));
             // Make sure we're allowed to view this ticket or message
             if (!isset($active_worker_memberships[$ticket->team_id])) {
                 echo "<H1>" . $translate->_('common.access_denied') . "</H1>";
                 return;
             }
             // Message Notes
             $notes = DAO_MessageNote::getByTicketId($ticket->id);
             $message_notes = array();
             // Index notes by message id
             if (is_array($notes)) {
                 foreach ($notes as $note) {
                     if (!isset($message_notes[$note->message_id])) {
                         $message_notes[$note->message_id] = array();
                     }
                     $message_notes[$note->message_id][$note->id] = $note;
                 }
             }
             $tpl->assign('message_notes', $message_notes);
             $tpl->assign('message', $message);
             $tpl->assign('ticket', $ticket);
             $tpl->display('file:' . $this->_TPL_PATH . 'print/message.tpl');
             break;
     }
 }
Esempio n. 5
0
File: App.php Progetto: Hildy/cerb5
 function saveEntryAction()
 {
     $active_worker = CerberusApplication::getActiveWorker();
     // Make sure we're an active worker
     if (empty($active_worker) || empty($active_worker->id)) {
         return;
     }
     @($id = DevblocksPlatform::importGPC($_REQUEST['id'], 'integer', 0));
     @($do_delete = DevblocksPlatform::importGPC($_REQUEST['do_delete'], 'integer', 0));
     @($email = DevblocksPlatform::importGPC($_POST['email'], 'string', ''));
     @($mood = DevblocksPlatform::importGPC($_POST['mood'], 'integer', 0));
     @($quote = DevblocksPlatform::importGPC($_POST['quote'], 'string', ''));
     @($url = DevblocksPlatform::importGPC($_POST['url'], 'string', ''));
     @($source_extension_id = DevblocksPlatform::importGPC($_POST['source_extension_id'], 'string', ''));
     @($source_id = DevblocksPlatform::importGPC($_POST['source_id'], 'integer', 0));
     // Translate email string into addy id, if exists
     $address_id = 0;
     if (!empty($email)) {
         if (null != ($author_address = DAO_Address::lookupAddress($email, true))) {
             $address_id = $author_address->id;
         }
     }
     // Delete entries
     if (!empty($id) && !empty($do_delete)) {
         if (null != ($entry = DAO_FeedbackEntry::get($id))) {
             // Only superusers and owners can delete entries
             if ($active_worker->is_superuser || $active_worker->id == $entry->worker_id) {
                 DAO_FeedbackEntry::delete($id);
             }
         }
         return;
     }
     // New or modify
     $fields = array(DAO_FeedbackEntry::QUOTE_MOOD => intval($mood), DAO_FeedbackEntry::QUOTE_TEXT => $quote, DAO_FeedbackEntry::QUOTE_ADDRESS_ID => intval($address_id), DAO_FeedbackEntry::SOURCE_URL => $url);
     // Only on new
     if (empty($id)) {
         $fields[DAO_FeedbackEntry::LOG_DATE] = time();
         $fields[DAO_FeedbackEntry::WORKER_ID] = $active_worker->id;
     }
     if (empty($id)) {
         // create
         $id = DAO_FeedbackEntry::create($fields);
         // Post-create actions
         if (!empty($source_extension_id) && !empty($source_id)) {
             switch ($source_extension_id) {
                 case 'feedback.source.ticket':
                     // Create a ticket comment about the feedback (to prevent dupes)
                     if (null == ($worker_address = DAO_Address::lookupAddress($active_worker->email))) {
                         break;
                     }
                     $comment_text = sprintf("== Capture Feedback ==\n" . "Author: %s\n" . "Mood: %s\n" . "\n" . "%s\n", !empty($author_address) ? $author_address->email : 'Anonymous', empty($mood) ? 'Neutral' : (1 == $mood ? 'Praise' : 'Criticism'), $quote);
                     $fields = array(DAO_TicketComment::ADDRESS_ID => $worker_address->id, DAO_TicketComment::COMMENT => $comment_text, DAO_TicketComment::CREATED => time(), DAO_TicketComment::TICKET_ID => intval($source_id));
                     DAO_TicketComment::create($fields);
                     break;
             }
         }
     } else {
         // modify
         DAO_FeedbackEntry::update($id, $fields);
     }
     // Custom field saves
     @($field_ids = DevblocksPlatform::importGPC($_POST['field_ids'], 'array', array()));
     DAO_CustomFieldValue::handleFormPost(ChCustomFieldSource_FeedbackEntry::ID, $id, $field_ids);
 }
Esempio n. 6
0
 private function _deleteIdAction($path)
 {
     $in_id = array_shift($path);
     if (empty($in_id)) {
         $this->_error("ID was not provided.");
     }
     if (null == ($note = DAO_TicketComment::get($in_id))) {
         $this->_error("ID is not valid.");
     }
     DAO_TicketComment::delete($note->id);
     $out_xml = new SimpleXMLElement('<success></success>');
     $this->_render($out_xml->asXML());
 }
Esempio n. 7
0
 function saveEntryAction()
 {
     $active_worker = CerberusApplication::getActiveWorker();
     // Make sure we're an active worker
     if (empty($active_worker) || empty($active_worker->id)) {
         return;
     }
     @($id = DevblocksPlatform::importGPC($_REQUEST['id'], 'integer', 0));
     @($do_delete = DevblocksPlatform::importGPC($_REQUEST['do_delete'], 'integer', 0));
     @($activity_id = DevblocksPlatform::importGPC($_POST['activity_id'], 'integer', 0));
     @($time_actual_mins = DevblocksPlatform::importGPC($_POST['time_actual_mins'], 'integer', 0));
     @($notes = DevblocksPlatform::importGPC($_POST['notes'], 'string', ''));
     @($org_str = DevblocksPlatform::importGPC($_POST['org'], 'string', ''));
     @($source_extension_id = DevblocksPlatform::importGPC($_POST['source_extension_id'], 'string', ''));
     @($source_id = DevblocksPlatform::importGPC($_POST['source_id'], 'integer', 0));
     // Translate org string into org id, if exists
     $org_id = 0;
     if (!empty($org_str)) {
         $org_id = DAO_ContactOrg::lookup($org_str, true);
     }
     // Delete entries
     if (!empty($id) && !empty($do_delete)) {
         if (null != ($entry = DAO_TimeTrackingEntry::get($id))) {
             // Check privs
             if ($active_worker->hasPriv('timetracking.actions.create') && $active_worker->id == $entry->worker_id || $active_worker->hasPriv('timetracking.actions.update_all')) {
                 DAO_TimeTrackingEntry::delete($id);
             }
         }
         return;
     }
     // New or modify
     $fields = array(DAO_TimeTrackingEntry::ACTIVITY_ID => intval($activity_id), DAO_TimeTrackingEntry::TIME_ACTUAL_MINS => intval($time_actual_mins), DAO_TimeTrackingEntry::NOTES => $notes, DAO_TimeTrackingEntry::DEBIT_ORG_ID => intval($org_id));
     // Only on new
     if (empty($id)) {
         $fields[DAO_TimeTrackingEntry::LOG_DATE] = time();
         $fields[DAO_TimeTrackingEntry::SOURCE_EXTENSION_ID] = $source_extension_id;
         $fields[DAO_TimeTrackingEntry::SOURCE_ID] = intval($source_id);
         $fields[DAO_TimeTrackingEntry::WORKER_ID] = intval($active_worker->id);
     }
     if (empty($id)) {
         // create
         $id = DAO_TimeTrackingEntry::create($fields);
         // Procedurally create a comment
         $translate = DevblocksPlatform::getTranslationService();
         switch ($source_extension_id) {
             // If ticket, add a comment about the timeslip to the ticket
             case 'timetracking.source.ticket':
                 $ticket_id = intval($source_id);
                 if (null != ($worker_address = DAO_Address::lookupAddress($active_worker->email, false))) {
                     if (!empty($activity_id)) {
                         $activity = DAO_TimeTrackingActivity::get($activity_id);
                     }
                     if (!empty($org_id)) {
                         $org = DAO_ContactOrg::get($org_id);
                     }
                     $comment = sprintf("== %s ==\n" . "%s %s\n" . "%s %d\n" . "%s %s (%s)\n" . "%s %s\n" . "%s %s\n", $translate->_('timetracking.ui.timetracking'), $translate->_('timetracking.ui.worker'), $active_worker->getName(), $translate->_('timetracking.ui.comment.time_spent'), $time_actual_mins, $translate->_('timetracking.ui.comment.activity'), !empty($activity) ? $activity->name : '', !empty($activity) && $activity->rate > 0.0 ? $translate->_('timetracking.ui.billable') : $translate->_('timetracking.ui.non_billable'), $translate->_('timetracking.ui.comment.organization'), !empty($org) ? $org->name : $translate->_('timetracking.ui.comment.not_set'), $translate->_('timetracking.ui.comment.notes'), $notes);
                     //timetracking.ui.billable timetracking.ui.non_billable
                     $fields = array(DAO_TicketComment::ADDRESS_ID => intval($worker_address->id), DAO_TicketComment::COMMENT => $comment, DAO_TicketComment::CREATED => time(), DAO_TicketComment::TICKET_ID => intval($ticket_id));
                     DAO_TicketComment::create($fields);
                 }
                 break;
         }
     } else {
         // modify
         DAO_TimeTrackingEntry::update($id, $fields);
     }
     // Custom field saves
     @($field_ids = DevblocksPlatform::importGPC($_POST['field_ids'], 'array', array()));
     DAO_CustomFieldValue::handleFormPost(ChCustomFieldSource_TimeEntry::ID, $id, $field_ids);
 }