/**
  * Parses a specified page ID and redirects to another ID if required.
  * 
  * @param WebSoccer $websoccer Website context.
  * @param I18n $i18n messages provider.
  * @param string $requestedPageId unfiltered Page ID that has been requested.
  * @return string target page ID to display.
  */
 public static function getTargetPageId(WebSoccer $websoccer, I18n $i18n, $requestedPageId)
 {
     $pageId = $requestedPageId;
     // set default page ID
     if ($pageId == NULL) {
         $pageId = DEFAULT_PAGE_ID;
     }
     // redirect to log-in form if website is generally protected
     $user = $websoccer->getUser();
     if ($websoccer->getConfig('password_protected') && $user->getRole() == ROLE_GUEST) {
         // list of page IDs that needs to be excluded.
         $freePageIds = array(LOGIN_PAGE_ID, 'register', 'register-success', 'activate-user', 'forgot-password', 'imprint', 'logout', 'termsandconditions');
         if (!$websoccer->getConfig('password_protected_startpage')) {
             $freePageIds[] = DEFAULT_PAGE_ID;
         }
         if (!in_array($pageId, $freePageIds)) {
             // create warning message
             $websoccer->addFrontMessage(new FrontMessage(MESSAGE_TYPE_WARNING, $i18n->getMessage('requireslogin_box_title'), $i18n->getMessage('requireslogin_box_message')));
             $pageId = LOGIN_PAGE_ID;
         }
     }
     // exception rule: If user clicks at breadcrumb navigation on team details, there will be no ID given, so redirect to leagues
     if ($pageId == 'team' && $websoccer->getRequestParameter('id') == null) {
         $pageId = 'leagues';
     }
     // prompt user to enter user name, after he has been created without user name (e.g. by a custom LoginMethod).
     if ($user->getRole() == ROLE_USER && !strlen($user->username)) {
         $pageId = ENTERUSERNAME_PAGE_ID;
     }
     return $pageId;
 }
 /**
  * Converts a date into a word, if it makes sense.
  * 
  * @param int $timestamp UNIX timestamp.
  * @param int $nowAsTimestamp Now as UNIX timestamp, considering server timezone.
  * @param I18n $i18n Messages context.
  * @return string Translated Today|Tomorrow|Yesterday or empty string if date is out of range.
  */
 public static function convertTimestampToWord($timestamp, $nowAsTimestamp, I18n $i18n)
 {
     if ($timestamp >= strtotime('tomorrow', $nowAsTimestamp) + 24 * 3600) {
         return '';
     }
     if ($timestamp >= strtotime('tomorrow', $nowAsTimestamp)) {
         return $i18n->getMessage('date_tomorrow');
     } else {
         if ($timestamp >= strtotime('today', $nowAsTimestamp)) {
             return $i18n->getMessage('date_today');
         } else {
             if ($timestamp >= strtotime('yesterday', $nowAsTimestamp)) {
                 return $i18n->getMessage('date_yesterday');
             }
         }
     }
     return '';
 }
 /**
  * Securely calls an action. Before the actual call, this handler will validate all parameters defined at the module.xml
  * and check the user permissions.
  * 
  * @param WebSoccer $website Current WebSoccer context.
  * @param DbConnection $db Data base connection.
  * @param I18n $i18n Messages context.
  * @param string $actionId ID of action to validate and execute.
  * @return string|NULL ID of page to display after the execution of this action or NULL if the current page shall be displayed.
  * @throws Exception if action could not be found, a double-submit occured, access is denied, controller could not be found 
  * or if the executed controller has thrown an Exception.
  */
 public static function handleAction(WebSoccer $website, DbConnection $db, I18n $i18n, $actionId)
 {
     if ($actionId == NULL) {
         return;
     }
     // check double-submit
     if (isset($_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_ACTIONID]) && $_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_ACTIONID] == $actionId && isset($_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_TIME]) && $_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_TIME] + DOUBLE_SUBMIT_CHECK_SECONDS > $website->getNowAsTimestamp()) {
         throw new Exception($i18n->getMessage('error_double_submit'));
     }
     $actionConfig = json_decode($website->getAction($actionId), true);
     $actionXml = ModuleConfigHelper::findModuleConfigAsXmlObject($actionConfig['module']);
     // check permissions
     $user = $website->getUser();
     // is admin action
     if (strpos($actionConfig['role'], 'admin') !== false) {
         if (!$user->isAdmin()) {
             throw new AccessDeniedException($i18n->getMessage('error_access_denied'));
         }
     } else {
         // all other actions
         $requiredRoles = explode(',', $actionConfig['role']);
         if (!in_array($user->getRole(), $requiredRoles)) {
             throw new AccessDeniedException($i18n->getMessage('error_access_denied'));
         }
     }
     // validate parameters
     $params = $actionXml->xpath('//action[@id = "' . $actionId . '"]/param');
     $validatedParams = array();
     if ($params) {
         $validatedParams = self::_validateParameters($params, $website, $i18n);
     }
     $controllerName = $actionConfig['controller'];
     // handle premium actions
     if (isset($actionConfig['premiumBalanceMin']) && $actionConfig['premiumBalanceMin']) {
         return self::_handlePremiumAction($website, $db, $i18n, $actionId, $actionConfig['premiumBalanceMin'], $validatedParams, $controllerName);
     }
     $actionReturn = self::_executeAction($website, $db, $i18n, $actionId, $controllerName, $validatedParams);
     // create log entry
     if (isset($actionConfig['log']) && $actionConfig['log'] && $website->getUser()->id) {
         ActionLogDataService::createOrUpdateActionLog($website, $db, $website->getUser()->id, $actionId);
     }
     return $actionReturn;
 }
 /**
  * Provides scout data set with specified ID. Throws exception if invalid ID.
  * 
  * @param WebSoccer $websoccer application context.
  * @param DbConnection $db DB connection-
  * @param I18n $i18n messages context.
  * @param int $scoutId ID of scout
  * @throws Exception if no scout with specified ID could be found.
  * @return array assoc array of scout data.
  */
 public static function getScoutById(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $scoutId)
 {
     $result = $db->querySelect("*", $websoccer->getConfig("db_prefix") . "_youthscout", "id = %d", $scoutId);
     $scout = $result->fetch_array();
     $result->free();
     if (!$scout) {
         throw new Exception($i18n->getMessage("youthteam_scouting_err_invalidscout"));
     }
     return $scout;
 }
 /**
  * Retrieves the latest notifications for the specified user.
  * 
  * @param WebSoccer $websoccer Application contex
  * @param DbConnection $db DB connection
  * @param I18n $i18n I18n context.
  * @param int $userId ID of user
  * @param int $teamId ID of user's currently selected team
  * @param int $limit maximum number of notifications to return.
  * @return array Array of assoc. arrays which represent a notification. A notification has keys id, eventdate, eventtype, seen, message, link
  */
 public static function getLatestNotifications(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $userId, $teamId, $limit)
 {
     $result = $db->querySelect('*', $websoccer->getConfig('db_prefix') . '_notification', 'user_id = %d AND (team_id = %d OR team_id IS NULL) ORDER BY eventdate DESC', array($userId, $teamId), $limit);
     $notifications = array();
     while ($row = $result->fetch_array()) {
         $notification = array('id' => $row['id'], 'eventdate' => $row['eventdate'], 'eventtype' => $row['eventtype'], 'seen' => $row['seen']);
         // prepare message
         if ($i18n->hasMessage($row['message_key'])) {
             $message = $i18n->getMessage($row['message_key']);
         } else {
             $message = $row['message_key'];
         }
         // replace place holders
         if (strlen($row['message_data'])) {
             $messageData = json_decode($row['message_data'], true);
             if ($messageData) {
                 foreach ($messageData as $placeholderName => $placeholderValue) {
                     $message = str_replace('{' . $placeholderName . '}', htmlspecialchars($placeholderValue, ENT_COMPAT, 'UTF-8'), $message);
                 }
             }
         }
         $notification['message'] = $message;
         // add target link
         $link = '';
         if ($row['target_pageid']) {
             if ($row['target_querystr']) {
                 $link = $websoccer->getInternalUrl($row['target_pageid'], $row['target_querystr']);
             } else {
                 $link = $websoccer->getInternalUrl($row['target_pageid']);
             }
         }
         $notification['link'] = $link;
         $notifications[] = $notification;
     }
     return $notifications;
 }
 public static function getMatchReportMessages(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $matchId)
 {
     $fromTable = $websoccer->getConfig('db_prefix') . '_matchreport AS R';
     $fromTable .= ' INNER JOIN ' . $websoccer->getConfig('db_prefix') . '_spiel_text AS T ON R.message_id = T.id';
     $columns['R.id'] = 'report_id';
     $columns['R.minute'] = 'minute';
     $columns['R.playernames'] = 'playerNames';
     $columns['R.goals'] = 'goals';
     $columns['T.nachricht'] = 'message';
     $columns['T.aktion'] = 'type';
     $columns['R.active_home'] = 'active_home';
     $whereCondition = 'R.match_id = %d ORDER BY R.minute DESC, R.id DESC';
     $parameters = $matchId;
     $reportmessages = array();
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters);
     $match = null;
     // required only for team name replacements
     $removeSlashes = get_magic_quotes_gpc();
     while ($reportmessage = $result->fetch_array()) {
         // replace placeholders
         $players = explode(';', $reportmessage['playerNames']);
         $rmsg = $reportmessage['message'];
         // remove escaping slashes
         if ($removeSlashes) {
             $rmsg = stripslashes($rmsg);
         }
         $msgKey = strip_tags($rmsg);
         if ($i18n->hasMessage($msgKey)) {
             $rmsg = $i18n->getMessage($msgKey);
         }
         for ($playerIndex = 1; $playerIndex <= count($players); $playerIndex++) {
             $rmsg = str_replace('{sp' . $playerIndex . '}', $players[$playerIndex - 1], $rmsg);
         }
         // replace team name placeholders
         if (strpos($rmsg, '{ma1}') || strpos($rmsg, '{ma2}')) {
             if ($match == null) {
                 $match = self::getMatchById($websoccer, $db, $matchId, FALSE);
             }
             if ($reportmessage['active_home']) {
                 $rmsg = str_replace('{ma1}', $match['match_home_name'], $rmsg);
                 $rmsg = str_replace('{ma2}', $match['match_guest_name'], $rmsg);
             } else {
                 $rmsg = str_replace('{ma1}', $match['match_guest_name'], $rmsg);
                 $rmsg = str_replace('{ma2}', $match['match_home_name'], $rmsg);
             }
         }
         $reportmessage['message'] = $rmsg;
         $reportmessages[] = $reportmessage;
     }
     $result->free();
     return $reportmessages;
 }
 /**
  * Check if team has enough budget to pay the secified salary.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB Connection.
  * @param I18n $i18n I18n.
  * @param int $clubId team id.
  * @param int $salary Salary which the user whishes to offer.
  * @throws Exception if budget is not enough. Exception contains translated message.
  */
 public static function validateWhetherTeamHasEnoughBudgetForSalaryBid(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $clubId, $salary)
 {
     // get salary sum of all players
     $result = $db->querySelect('SUM(vertrag_gehalt) AS salary_sum', $websoccer->getConfig('db_prefix') . '_spieler', 'verein_id = %d', $clubId);
     $players = $result->fetch_array();
     $result->free();
     // check if team can afford at least X matches
     $minBudget = ($players['salary_sum'] + $salary) * 2;
     $team = self::getTeamSummaryById($websoccer, $db, $clubId);
     if ($team['team_budget'] < $minBudget) {
         throw new Exception($i18n->getMessage("extend-contract_cannot_afford_offer"));
     }
 }
    /**
     * Renders a selection field for a data table entry.
     * Up to 20 items will be displayed as usual selection box. Above as Autocomplete field.
     * 
     * @param I18n $i18n Messages context.
     * @param string $fieldId ID of field.
     * @param array $fieldInfo assoc. array with at least keys 'entity', 'jointable' and 'labelcolumns'.
     * @param int $fieldValue pre-selected ID.
     */
    public static function createForeignKeyField($i18n, $fieldId, $fieldInfo, $fieldValue)
    {
        $website = WebSoccer::getInstance();
        $db = DbConnection::getInstance();
        $fromTable = $website->getConfig('db_prefix') . '_' . $fieldInfo['jointable'];
        // count total items
        $result = $db->querySelect('COUNT(*) AS hits', $fromTable, '1=1', '');
        $items = $result->fetch_array();
        $result->free();
        // render usual selection box
        if ($items['hits'] <= 20) {
            echo '<select id=\'' . $fieldId . '\' name=\'' . $fieldId . '\'>';
            echo '<option value=\'\'>' . $i18n->getMessage('manage_select_placeholder') . '</option>';
            $whereCondition = '1=1 ORDER BY ' . $fieldInfo['labelcolumns'] . ' ASC';
            $result = $db->querySelect('id, ' . $fieldInfo['labelcolumns'], $fromTable, $whereCondition, '', 2000);
            while ($row = $result->fetch_array()) {
                $labels = explode(',', $fieldInfo['labelcolumns']);
                $label = '';
                $first = TRUE;
                foreach ($labels as $labelColumn) {
                    if (!$first) {
                        $label .= ' - ';
                    }
                    $first = FALSE;
                    $label .= $row[trim($labelColumn)];
                }
                echo '<option value=\'' . $row['id'] . '\'';
                if ($fieldValue == $row['id']) {
                    echo ' selected';
                }
                echo '>' . escapeOutput($label) . '</option>';
            }
            $result->free();
            echo '</select>';
            // render AJAXified item picker
        } else {
            echo '<input type=\'hidden\' class=\'pkpicker\' id=\'' . $fieldId . '\' name=\'' . $fieldId . '\' 
					value=\'' . $fieldValue . '\' data-dbtable=\'' . $fieldInfo['jointable'] . '\' data-labelcolumns=\'' . $fieldInfo['labelcolumns'] . '\' data-placeholder=\'' . $i18n->getMessage('manage_select_placeholder') . '\'>';
        }
        echo ' <a href=\'?site=manage&entity=' . $fieldInfo['entity'] . '&show=add\' title=\'' . $i18n->getMessage('manage_add') . '\'><i class=\'icon-plus-sign\'></i></a>';
    }
 /**
  * Provides match report items in current language and with replaced placeholders.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param I18n $i18n Messages context.
  * @param int $matchId ID of match.
  * @return array list of match report items with translated messages.
  */
 public static function getMatchReportItems(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $matchId)
 {
     // query
     $result = $db->querySelect("*", $websoccer->getConfig("db_prefix") . "_youthmatch_reportitem", "match_id = %d ORDER BY minute ASC", $matchId);
     // create formatted items
     $items = array();
     while ($item = $result->fetch_array()) {
         $message = $i18n->getMessage($item["message_key"]);
         // replace place holders
         if (strlen($item["message_data"])) {
             $messageData = json_decode($item["message_data"], true);
             if ($messageData) {
                 foreach ($messageData as $placeholderName => $placeholderValue) {
                     $message = str_replace("{" . $placeholderName . "}", htmlspecialchars($placeholderValue, ENT_COMPAT, "UTF-8"), $message);
                 }
             }
         }
         // create mapped item
         $items[] = array("minute" => $item["minute"], "active_home" => $item["home_on_ball"], "message_key" => $item["message_key"], "message" => $message);
     }
     $result->free();
     return $items;
 }