<commit_before><?php
/**
 * Messages from applicants
 * @author <NAME> <<EMAIL>>
 * @package jazzee
 * @subpackage applicants
 */
class ApplicantsMessagesController extends \Jazzee\AdminController {
  const MENU = 'Applicants';
  const TITLE = 'Messages';
  const PATH = 'applicants/messages';
  
  const ACTION_INDEX = 'View Messages';
  
  const MIN_INTERVAL_APPLICANTS = 3500; //1 hour minus a bit
  const MIN_INTERVAL_PROGRAMS = 86300; //24 hours minus a bit
  
  /**
   * List all unread messages
   */
  public function actionIndex(){
    $allThreads = $this->_em->getRepository('\Jazzee\Entity\Thread')->findByApplication($this->_application);
    $threads = array();
    foreach($allThreads as $thread) if($thread->hasUnreadMessage(\Jazzee\Entity\Message::APPLICANT)) $threads[] = $thread;
    $this->setVar('threads', $threads);
  }
  
  /**
   * List all messages
   */
  public function actionAll(){
    $threads = $this->_em->getRepository('\Jazzee\Entity\Thread')->findByApplication($this->_application);
    $this->setVar('threads', $threads);
  }
  
  /**
   * View a single message
   * 
   * @param integer $threadId
   */
  public function actionSingle($threadId) {
    $thread = $this->_em->getRepository('\Jazzee\Entity\Thread')->find($threadId);
    if(!$thread) throw new \Jazzee\Exception("{$threadId} is not a valid thread id");
    $applicant = $this->getApplicantById($thread->getApplicant()->getId());
    $this->setVar('thread', $thread);
  }
  
  /**
   * Mark message as unread
   * 
   * @param integer $messageId
   */
  public function actionMarkUnread($messageId) {
    $message = $this->_em->getRepository('\Jazzee\Entity\Message')->find($messageId);
    if(!$message) throw new \Jazzee\Exception("{$messageId} is not a valid message id");
    $applicant = $this->getApplicantById($message->getThread()->getApplicant()->getId());
    $message->unRead();
    $this->_em->persist($message);
    $this->addMessage('success', 'Message marked as unread');
    $this->redirectPath('applicants/messages');
  }
  
  /**
   * Reply to a message
   * 
   * @param integer $threadId
   */
  public function actionReply($threadId) {
    $thread = $this->_em->getRepository('\Jazzee\Entity\Thread')->find($threadId);
    if(!$thread) throw new \Jazzee\Exception("{$threadId} is not a valid thread id");
    $applicant = $this->getApplicantById($thread->getApplicant()->getId());
    $this->setVar('thread', $thread);
    
    $form = new \Foundation\Form();
    $form->setAction($this->path('applicants/messages/reply/' . $thread->getId()));
    
    $field = $form->newField();
    $field->setLegend('Reply');
    
    $element = $field->newElement('Textarea', 'text');
    $element->setLabel('Your Reply');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    $form->newButton('submit', 'Submit');
    $this->setVar('form', $form);
    
    if($input = $form->processInput($this->post)){
      $reply = new \Jazzee\Entity\Message();
      $reply->setSender(\Jazzee\Entity\Message::PROGRAM);
      $reply->setText($input->get('text'));
      $thread->addMessage($reply);
      $this->_em->persist($reply);
      $this->addMessage('success', 'Your reply has been sent.');
      $this->redirectPath('applicants/messages');
    }
  }
  
  /**
   * New Message to applicant
   * @param $applicantId
   */
  public function actionNew($applicantId = false) {
    if($applicantId) $applicant = $this->getApplicantById($applicantId);
    
    $form = new \Foundation\Form();
    $path = 'applicants/messages/new';
    if($applicantId) $path .= '/' . $applicantId;
    $form->setAction($this->path($path));
    $field = $form->newField();
    $field->setLegend('New Message');
    
    if($applicantId){
      $element = $field->newElement('Plaintext', 'name');
      $element->setLabel('To');
      $element->setValue($applicant->getFullName());
      
      $element = $field->newElement('HiddenInput', 'to');
      $element->setValue($applicant->getId());
    } else {
      $element = $field->newElement('SelectList', 'to');
      $element->setLabel('To');
      foreach($this->_em->getRepository('\Jazzee\Entity\Applicant')->findApplicantsByName('%', '%', $this->_application) as $applicant){
        $element->newItem($applicant->getId(), $applicant->getLastName() . ', ' . $applicant->getFirstName());
      }
      $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    }
    $element = $field->newElement('TextInput', 'subject');
    $element->setLabel('Subject');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    
    $element = $field->newElement('Textarea', 'text');
    $element->setLabel('Message');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    $form->newButton('submit', 'Submit');
    $this->setVar('form', $form);
    
    if($input = $form->processInput($this->post)){
      $thread = new \Jazzee\Entity\Thread();
      $thread->setSubject($input->get('subject'));
      $applicant = $this->getApplicantById($input->get('to'));
      $thread->setApplicant($applicant);
      
      $message = new \Jazzee\Entity\Message();
      $message->setSender(\Jazzee\Entity\Message::PROGRAM);
      $message->setText($input->get('text'));
      $thread->addMessage($message);
      $this->_em->persist($thread);
      $this->_em->persist($message);
      $this->addMessage('success', 'Your message has been sent.');
      $this->redirectPath('applicants/messages');
    }
  }
  
  /**
   * Check for new messages in each program and email the administrator
   * 
   * @param AdminCronController $cron
   */
  public static function runCron(AdminCronController $cron){
    $threads = $cron->getEntityManager()->getRepository('\Jazzee\Entity\Thread')->findAll();
    if(time() - (int)$cron->getVar('applicantsMessagesApplicantsLastRun') > self::MIN_INTERVAL_APPLICANTS){
      $lastRun = new DateTime();
      $lastRun->setTimeStamp((int)$cron->getVar('applicantsMessagesApplicantsLastRun'));
      $cron->setVar('applicantsMessagesApplicantsLastRun', time());
      $applicants = array();
      foreach($threads as $thread){
        if($thread->hasUnreadMessage(\Jazzee\Entity\Message::PROGRAM)){
          $lastUnreadMessageCreatedAt = $thread->getLastUnreadMessage(\Jazzee\Entity\Message::PROGRAM)->getCreatedAt();
          //if created since our last run or remind every 7 days
          if(($lastUnreadMessageCreatedAt > $lastRun) OR ($lastUnreadMessageCreatedAt->diff(new DateTime('now'))->days%7 == 0)){
            if(!array_key_exists($thread->getApplicant()->getId(), $applicants)){
              $applicants[$thread->getApplicant()->getId()] = array(
                'applicant' => $thread->getApplicant(),
                'count' => 0
              );
            }
            $applicants[$thread->getApplicant()->getId()]['count']++;
          }
        }
      }
      foreach($applicants as $arr){
        $message = $cron->newMessage();
        $message->AddAddress(
          $arr['applicant']->getEmail(),
          $arr['applicant']->getFullName());
        $message->Subject = 'New Message from ' . $arr['applicant']->getApplication()->getCycle()->getName() . ' ' . $arr['applicant']->getApplication()->getProgram()->getName();
        $body = 'You have ' . $arr['count'] . ' unread message(s) from the ' . $arr['applicant']->getApplication()->getCycle()->getName() . ' ' . $arr['applicant']->getApplication()->getProgram()->getName() . '.' .
          "\nYou can review them by logging into the application at: " . $cron->applyPath('apply/' . $arr['applicant']->getApplication()->getProgram()->getShortName() . '/' . $arr['applicant']->getApplication()->getCycle()->getName() . '/applicant/login');
        $message->Body = $body;
        $message->Send();
      }
    }
    
    if(time() - (int)$cron->getVar('applicantsMessagesProgramsLastRun') > self::MIN_INTERVAL_PROGRAMS){
      $lastRun = new DateTime();
      $lastRun->setTimeStamp((int)$cron->getVar('applicantsMessagesProgramsLastRun'));
      $cron->setVar('applicantsMessagesProgramsLastRun', time());
      $applications = array();<commit_msg>only send messages to applicants once if it is after 7 days<commit_after><?php
/**
 * Messages from applicants
 * @author <NAME> <<EMAIL>>
 * @package jazzee
 * @subpackage applicants
 */
class ApplicantsMessagesController extends \Jazzee\AdminController {
  const MENU = 'Applicants';
  const TITLE = 'Messages';
  const PATH = 'applicants/messages';
  
  const ACTION_INDEX = 'View Messages';
  
  const MIN_INTERVAL_APPLICANTS = 3500; //1 hour minus a bit
  const MIN_INTERVAL_PROGRAMS = 86300; //24 hours minus a bit
  
  /**
   * List all unread messages
   */
  public function actionIndex(){
    $allThreads = $this->_em->getRepository('\Jazzee\Entity\Thread')->findByApplication($this->_application);
    $threads = array();
    foreach($allThreads as $thread) if($thread->hasUnreadMessage(\Jazzee\Entity\Message::APPLICANT)) $threads[] = $thread;
    $this->setVar('threads', $threads);
  }
  
  /**
   * List all messages
   */
  public function actionAll(){
    $threads = $this->_em->getRepository('\Jazzee\Entity\Thread')->findByApplication($this->_application);
    $this->setVar('threads', $threads);
  }
  
  /**
   * View a single message
   * 
   * @param integer $threadId
   */
  public function actionSingle($threadId) {
    $thread = $this->_em->getRepository('\Jazzee\Entity\Thread')->find($threadId);
    if(!$thread) throw new \Jazzee\Exception("{$threadId} is not a valid thread id");
    $applicant = $this->getApplicantById($thread->getApplicant()->getId());
    $this->setVar('thread', $thread);
  }
  
  /**
   * Mark message as unread
   * 
   * @param integer $messageId
   */
  public function actionMarkUnread($messageId) {
    $message = $this->_em->getRepository('\Jazzee\Entity\Message')->find($messageId);
    if(!$message) throw new \Jazzee\Exception("{$messageId} is not a valid message id");
    $applicant = $this->getApplicantById($message->getThread()->getApplicant()->getId());
    $message->unRead();
    $this->_em->persist($message);
    $this->addMessage('success', 'Message marked as unread');
    $this->redirectPath('applicants/messages');
  }
  
  /**
   * Reply to a message
   * 
   * @param integer $threadId
   */
  public function actionReply($threadId) {
    $thread = $this->_em->getRepository('\Jazzee\Entity\Thread')->find($threadId);
    if(!$thread) throw new \Jazzee\Exception("{$threadId} is not a valid thread id");
    $applicant = $this->getApplicantById($thread->getApplicant()->getId());
    $this->setVar('thread', $thread);
    
    $form = new \Foundation\Form();
    $form->setAction($this->path('applicants/messages/reply/' . $thread->getId()));
    
    $field = $form->newField();
    $field->setLegend('Reply');
    
    $element = $field->newElement('Textarea', 'text');
    $element->setLabel('Your Reply');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    $form->newButton('submit', 'Submit');
    $this->setVar('form', $form);
    
    if($input = $form->processInput($this->post)){
      $reply = new \Jazzee\Entity\Message();
      $reply->setSender(\Jazzee\Entity\Message::PROGRAM);
      $reply->setText($input->get('text'));
      $thread->addMessage($reply);
      $this->_em->persist($reply);
      $this->addMessage('success', 'Your reply has been sent.');
      $this->redirectPath('applicants/messages');
    }
  }
  
  /**
   * New Message to applicant
   * @param $applicantId
   */
  public function actionNew($applicantId = false) {
    if($applicantId) $applicant = $this->getApplicantById($applicantId);
    
    $form = new \Foundation\Form();
    $path = 'applicants/messages/new';
    if($applicantId) $path .= '/' . $applicantId;
    $form->setAction($this->path($path));
    $field = $form->newField();
    $field->setLegend('New Message');
    
    if($applicantId){
      $element = $field->newElement('Plaintext', 'name');
      $element->setLabel('To');
      $element->setValue($applicant->getFullName());
      
      $element = $field->newElement('HiddenInput', 'to');
      $element->setValue($applicant->getId());
    } else {
      $element = $field->newElement('SelectList', 'to');
      $element->setLabel('To');
      foreach($this->_em->getRepository('\Jazzee\Entity\Applicant')->findApplicantsByName('%', '%', $this->_application) as $applicant){
        $element->newItem($applicant->getId(), $applicant->getLastName() . ', ' . $applicant->getFirstName());
      }
      $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    }
    $element = $field->newElement('TextInput', 'subject');
    $element->setLabel('Subject');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    
    $element = $field->newElement('Textarea', 'text');
    $element->setLabel('Message');
    $element->addValidator(new \Foundation\Form\Validator\NotEmpty($element));
    $form->newButton('submit', 'Submit');
    $this->setVar('form', $form);
    
    if($input = $form->processInput($this->post)){
      $thread = new \Jazzee\Entity\Thread();
      $thread->setSubject($input->get('subject'));
      $applicant = $this->getApplicantById($input->get('to'));
      $thread->setApplicant($applicant);
      
      $message = new \Jazzee\Entity\Message();
      $message->setSender(\Jazzee\Entity\Message::PROGRAM);
      $message->setText($input->get('text'));
      $thread->addMessage($message);
      $this->_em->persist($thread);
      $this->_em->persist($message);
      $this->addMessage('success', 'Your message has been sent.');
      $this->redirectPath('applicants/messages');
    }
  }
  
  /**
   * Check for new messages in each program and email the administrator
   * 
   * @param AdminCronController $cron
   */
  public static function runCron(AdminCronController $cron){
    $threads = $cron->getEntityManager()->getRepository('\Jazzee\Entity\Thread')->findAll();
    if(time() - (int)$cron->getVar('applicantsMessagesApplicantsLastRun') > self::MIN_INTERVAL_APPLICANTS){
      $lastRun = new DateTime();
      $lastRun->setTimeStamp((int)$cron->getVar('applicantsMessagesApplicantsLastRun'));
      $cron->setVar('applicantsMessagesApplicantsLastRun', time());
      $applicants = array();
      foreach($threads as $thread){
        if($thread->hasUnreadMessage(\Jazzee\Entity\Message::PROGRAM)){
          $lastUnreadMessageCreatedAt = $thread->getLastUnreadMessage(\Jazzee\Entity\Message::PROGRAM)->getCreatedAt();
          //if created since our last run or remind every 7 days (only once if the hour it was sent is the same as the current hour)
          if(($lastUnreadMessageCreatedAt > $lastRun) OR ($lastUnreadMessageCreatedAt->diff(new DateTime('now'))->days%7 == 0 AND $lastUnreadMessageCreatedAt->diff(new DateTime('now'))->h == 0)){
            if(!array_key_exists($thread->getApplicant()->getId(), $applicants)){
              $applicants[$thread->getApplicant()->getId()] = array(
                'applicant' => $thread->getApplicant(),
                'count' => 0
              );
            }
            $applicants[$thread->getApplicant()->getId()]['count']++;
          }
        }
      }
      foreach($applicants as $arr){
        $message = $cron->newMessage();
        $message->AddAddress(
          $arr['applicant']->getEmail(),
          $arr['applicant']->getFullName());
        $message->Subject = 'New Message from ' . $arr['applicant']->getApplication()->getCycle()->getName() . ' ' . $arr['applicant']->getApplication()->getProgram()->getName();
        $body = 'You have ' . $arr['count'] . ' unread message(s) from the ' . $arr['applicant']->getApplication()->getCycle()->getName() . ' ' . $arr['applicant']->getApplication()->getProgram()->getName() . '.' .
          "\nYou can review them by logging into the application at: " . $cron->applyPath('apply/' . $arr['applicant']->getApplication()->getProgram()->getShortName() . '/' . $arr['applicant']->getApplication()->getCycle()->getName() . '/applicant/login');
        $message->Body = $body;
        $message->Send();
      }
    }
    if(time() - (int)$cron->getVar('applicantsMessagesProgramsLastRun') > self::MIN_INTERVAL_PROGRAMS){
      $lastRun = new DateTime();
      $lastRun->setTimeStamp((int)$cron->getVar('applicantsMessagesProgramsLastRun'));
      $cron->setVar('applicantsMessagesProgramsLastRun', time());
      $applications = array();
{'fraction_non_alphanumeric': 0.18880822746521475, 'fraction_numerical': 0.00205686630369026, 'mean_word_length': 3.660558218212574, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 329, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '524022', 'n_tokens_mistral': 5198, 'n_tokens_neox': 5046, 'n_words': 825}