original_string: public function calculateEndDate()
      {
          // Exclude the tokens whose end date is calculated from the track end date
          $excludeWheres[] = sprintf(
                  "gro_valid_for_source = '%s' AND gro_valid_for_field = 'gr2t_end_date'",
                  \Gems_Tracker_Engine_StepEngineAbstract::RESPONDENT_TRACK_TABLE
                  );
  
          // Exclude the tokens whose start date is calculated from the track end date, while the
          // end date is calculated using that same start date
          $excludeWheres[] = sprintf(
                  "gro_valid_after_source = '%s' AND gro_valid_after_field = 'gr2t_end_date' AND
                      gro_id_round = gro_valid_for_id AND
                      gro_valid_for_source = '%s' AND gro_valid_for_field = 'gto_valid_from'",
                  \Gems_Tracker_Engine_StepEngineAbstract::RESPONDENT_TRACK_TABLE,
                  \Gems_Tracker_Engine_StepEngineAbstract::TOKEN_TABLE
                  );
          // In future we may want to add some nesting to this, e.g. tokens with an end date calculated
          // from another token whose... for the time being users should use the end date directly in
          // each token, otherwise the end date will not be calculated
  
          $maxExpression = "
              CASE
              WHEN SUM(
                  CASE WHEN COALESCE(gto_completion_time, gto_valid_until) IS NULL THEN 1 ELSE 0 END
                  ) > 0
              THEN NULL
              ELSE MAX(COALESCE(gto_completion_time, gto_valid_until))
              END as enddate";
  
          $tokenSelect = $this->tracker->getTokenSelect(array(new \Zend_Db_Expr($maxExpression)));
          $tokenSelect->andReceptionCodes(array())
                  ->andRounds(array())
                  ->forRespondentTrack($this->_respTrackId)
                  ->onlySucces();
  
          foreach ($excludeWheres as $where) {
              $tokenSelect->forWhere('NOT (' . $where . ')');
          }
  
          $endDate = $tokenSelect->fetchOne();
  
          // \MUtil_Echo::track($endDate, $tokenSelect->getSelect()->__toString());
  
          if (false === $endDate) {
              return null;;
          } else {
              return $endDate;
          }
      }
code: public function calculateEndDate()
      {
          // Exclude the tokens whose end date is calculated from the track end date
          $excludeWheres[] = sprintf(
                  "gro_valid_for_source = '%s' AND gro_valid_for_field = 'gr2t_end_date'",
                  \Gems_Tracker_Engine_StepEngineAbstract::RESPONDENT_TRACK_TABLE
                  );
  
          // Exclude the tokens whose start date is calculated from the track end date, while the
          // end date is calculated using that same start date
          $excludeWheres[] = sprintf(
                  "gro_valid_after_source = '%s' AND gro_valid_after_field = 'gr2t_end_date' AND
                      gro_id_round = gro_valid_for_id AND
                      gro_valid_for_source = '%s' AND gro_valid_for_field = 'gto_valid_from'",
                  \Gems_Tracker_Engine_StepEngineAbstract::RESPONDENT_TRACK_TABLE,
                  \Gems_Tracker_Engine_StepEngineAbstract::TOKEN_TABLE
                  );
          // In future we may want to add some nesting to this, e.g. tokens with an end date calculated
          // from another token whose... for the time being users should use the end date directly in
          // each token, otherwise the end date will not be calculated
  
          $maxExpression = "
              CASE
              WHEN SUM(
                  CASE WHEN COALESCE(gto_completion_time, gto_valid_until) IS NULL THEN 1 ELSE 0 END
                  ) > 0
              THEN NULL
              ELSE MAX(COALESCE(gto_completion_time, gto_valid_until))
              END as enddate";
  
          $tokenSelect = $this->tracker->getTokenSelect(array(new \Zend_Db_Expr($maxExpression)));
          $tokenSelect->andReceptionCodes(array())
                  ->andRounds(array())
                  ->forRespondentTrack($this->_respTrackId)
                  ->onlySucces();
  
          foreach ($excludeWheres as $where) {
              $tokenSelect->forWhere('NOT (' . $where . ')');
          }
  
          $endDate = $tokenSelect->fetchOne();
  
          // \MUtil_Echo::track($endDate, $tokenSelect->getSelect()->__toString());
  
          if (false === $endDate) {
              return null;;
          } else {
              return $endDate;
          }
      }
code_tokens: public function calculateEndDate ( ) { // Exclude the tokens whose end date is calculated from the track end date $ excludeWheres [ ] = sprintf ( "gro_valid_for_source = '%s' AND gro_valid_for_field = 'gr2t_end_date'" , \ Gems_Tracker_Engine_StepEngineAbstract :: RESPONDENT_TRACK_TABLE ) ; // Exclude the tokens whose start date is calculated from the track end date, while the // end date is calculated using that same start date $ excludeWheres [ ] = sprintf ( "gro_valid_after_source = '%s' AND gro_valid_after_field = 'gr2t_end_date' AND
                      gro_id_round = gro_valid_for_id AND
                      gro_valid_for_source = '%s' AND gro_valid_for_field = 'gto_valid_from'" , \ Gems_Tracker_Engine_StepEngineAbstract :: RESPONDENT_TRACK_TABLE , \ Gems_Tracker_Engine_StepEngineAbstract :: TOKEN_TABLE ) ; // In future we may want to add some nesting to this, e.g. tokens with an end date calculated // from another token whose... for the time being users should use the end date directly in // each token, otherwise the end date will not be calculated $ maxExpression = "
              CASE
              WHEN SUM(
                  CASE WHEN COALESCE(gto_completion_time, gto_valid_until) IS NULL THEN 1 ELSE 0 END
                  ) > 0
              THEN NULL
              ELSE MAX(COALESCE(gto_completion_time, gto_valid_until))
              END as enddate" ; $ tokenSelect = $ this -> tracker -> getTokenSelect ( array ( new \ Zend_Db_Expr ( $ maxExpression ) ) ) ; $ tokenSelect -> andReceptionCodes ( array ( ) ) -> andRounds ( array ( ) ) -> forRespondentTrack ( $ this -> _respTrackId ) -> onlySucces ( ) ; foreach ( $ excludeWheres as $ where ) { $ tokenSelect -> forWhere ( 'NOT (' . $ where . ')' ) ; } $ endDate = $ tokenSelect -> fetchOne ( ) ; // \MUtil_Echo::track($endDate, $tokenSelect->getSelect()->__toString()); if ( false === $ endDate ) { return null ; ; } else { return $ endDate ; } }
docstring: Calculates the track end date
  
  The end date can be calculated when:
  - all active tokens have a completion date
  - or all active tokens have a valid until date
  - or the end date of the tokens is calculated using the end date
  
  You can overrule this calculation at the project level.
  
  @return string or null
docstring_tokens: Calculates the track end date