This commit introduces several enhancements to the ChronoTrack API, focusing on entry handling and diagnostic capabilities. New functions are added to normalize and summarize entry data, improving the management of entry-related information. Additionally, the diagnostic functionality is updated to include entry endpoints, providing more comprehensive insights during API diagnostics. These changes aim to enhance the overall usability and effectiveness of the ChronoTrack API for event management.
810 lines
28 KiB
PHP
810 lines
28 KiB
PHP
<?php
|
|
/**
|
|
* MSIN API ChronoTrack — lecture / filtrage des ressources CT (event, race).
|
|
*/
|
|
|
|
function fxChronotrackApiNormalizeEntityList($mixPayload, $strEntityKey) {
|
|
$arrOut = array();
|
|
|
|
if (!is_array($mixPayload)) {
|
|
return $arrOut;
|
|
}
|
|
|
|
if (isset($mixPayload[$strEntityKey]) && is_array($mixPayload[$strEntityKey])) {
|
|
$mixList = $mixPayload[$strEntityKey];
|
|
if (fxChronotrackApiIsAssocArray($mixList)) {
|
|
$arrOut[] = $mixList;
|
|
} else {
|
|
$arrOut = $mixList;
|
|
}
|
|
return $arrOut;
|
|
}
|
|
|
|
// Pluriel courant côté CT (ex. "races" pour clé "race")
|
|
$strPluralKey = $strEntityKey . 's';
|
|
if ($strEntityKey !== $strPluralKey && isset($mixPayload[$strPluralKey]) && is_array($mixPayload[$strPluralKey])) {
|
|
$mixList = $mixPayload[$strPluralKey];
|
|
if (fxChronotrackApiIsAssocArray($mixList)) {
|
|
$arrOut[] = $mixList;
|
|
} else {
|
|
$arrOut = $mixList;
|
|
}
|
|
return $arrOut;
|
|
}
|
|
|
|
// Clé CT Live pour GET event/{id}/race (ex. event_race, pas race)
|
|
if ($strEntityKey === 'race') {
|
|
foreach (array('event_race') as $strAltKey) {
|
|
if (!isset($mixPayload[$strAltKey]) || !is_array($mixPayload[$strAltKey])) {
|
|
continue;
|
|
}
|
|
$mixList = $mixPayload[$strAltKey];
|
|
if (fxChronotrackApiIsAssocArray($mixList)) {
|
|
$arrOut[] = $mixList;
|
|
} else {
|
|
$arrOut = $mixList;
|
|
}
|
|
return $arrOut;
|
|
}
|
|
}
|
|
|
|
// Clé CT Live pour GET event/{id}/entry (ex. event_entry, pas entry)
|
|
if ($strEntityKey === 'entry') {
|
|
foreach (array('event_entry', 'entries') as $strAltKey) {
|
|
if (!isset($mixPayload[$strAltKey]) || !is_array($mixPayload[$strAltKey])) {
|
|
continue;
|
|
}
|
|
$mixList = $mixPayload[$strAltKey];
|
|
if (fxChronotrackApiIsAssocArray($mixList)) {
|
|
$arrOut[] = $mixList;
|
|
} else {
|
|
$arrOut = $mixList;
|
|
}
|
|
return $arrOut;
|
|
}
|
|
}
|
|
|
|
if (fxChronotrackApiIsAssocArray($mixPayload) && (
|
|
isset($mixPayload['race_id']) || isset($mixPayload['reg_choice_id'])
|
|
|| isset($mixPayload['entry_id']) || isset($mixPayload['external_id'])
|
|
)) {
|
|
return array($mixPayload);
|
|
}
|
|
|
|
if (fxChronotrackApiIsAssocArray($mixPayload) && isset($mixPayload['id'])
|
|
&& !isset($mixPayload['event_id']) && !isset($mixPayload['event_name'])
|
|
) {
|
|
return array($mixPayload);
|
|
}
|
|
|
|
if (!fxChronotrackApiIsAssocArray($mixPayload)) {
|
|
return $mixPayload;
|
|
}
|
|
|
|
return $arrOut;
|
|
}
|
|
|
|
function fxChronotrackApiIsAssocArray($arr) {
|
|
if (!is_array($arr) || $arr === array()) {
|
|
return false;
|
|
}
|
|
return array_keys($arr) !== range(0, count($arr) - 1);
|
|
}
|
|
|
|
function fxChronotrackApiEntityId($arrEntity) {
|
|
foreach (array('entry_id', 'reg_choice_id', 'race_id', 'event_id', 'id') as $strKey) {
|
|
if (isset($arrEntity[$strKey]) && $arrEntity[$strKey] !== '') {
|
|
return (string)$arrEntity[$strKey];
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiEntityExternalId($arrEntity) {
|
|
foreach (array('external_id', 'entry_external_id', 'ext_id', 'external_entry_id') as $strKey) {
|
|
if (isset($arrEntity[$strKey]) && $arrEntity[$strKey] !== '') {
|
|
return (string)$arrEntity[$strKey];
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiEntityEntryLabel($arrEntity) {
|
|
$strFirst = fxChronotrackApiRaceField($arrEntity, array('first_name', 'entry_first_name', 'fname'));
|
|
$strLast = fxChronotrackApiRaceField($arrEntity, array('last_name', 'entry_last_name', 'lname'));
|
|
if ($strFirst !== '' || $strLast !== '') {
|
|
return trim($strFirst . ' ' . $strLast);
|
|
}
|
|
|
|
return fxChronotrackApiEntityName($arrEntity);
|
|
}
|
|
|
|
function fxChronotrackApiEntityName($arrEntity) {
|
|
foreach (array(
|
|
'reg_choice_name', 'registration_choice_name', 'choice_name',
|
|
'event_name', 'race_name', 'name', 'title',
|
|
'entry_name', 'athlete_name',
|
|
) as $strKey) {
|
|
if (!empty($arrEntity[$strKey])) {
|
|
return trim((string)$arrEntity[$strKey]);
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiRaceField($arrEntity, $arrKeys) {
|
|
foreach ($arrKeys as $strKey) {
|
|
if (!isset($arrEntity[$strKey])) {
|
|
continue;
|
|
}
|
|
$strVal = trim((string)$arrEntity[$strKey]);
|
|
if ($strVal !== '') {
|
|
return $strVal;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiFormatRaceDistanceLabel($arrEntity) {
|
|
$strDist = fxChronotrackApiRaceField($arrEntity, array(
|
|
'race_course_distance', 'course_distance', 'race_distance', 'distance', 'race_length',
|
|
));
|
|
if ($strDist === '') {
|
|
return '';
|
|
}
|
|
|
|
$strUnit = fxChronotrackApiRaceField($arrEntity, array(
|
|
'race_pref_distance_unit', 'course_distance_type', 'course_distance_unit',
|
|
'distance_unit', 'race_distance_unit', 'distance_type',
|
|
));
|
|
|
|
if (is_numeric($strDist) && $strUnit !== '') {
|
|
$fltDist = floatval($strDist);
|
|
if ($strUnit === 'kilometers' && $fltDist >= 1000) {
|
|
$strDist = rtrim(rtrim(number_format($fltDist / 1000, 1, '.', ''), '0'), '.') . ' km';
|
|
return $strDist;
|
|
}
|
|
if ($strUnit === 'meters') {
|
|
$strDist = rtrim(rtrim(number_format($fltDist, 0, '.', ''), '0'), '.') . ' m';
|
|
return $strDist;
|
|
}
|
|
}
|
|
|
|
if ($strUnit !== '' && stripos($strDist, $strUnit) === false) {
|
|
return $strDist . ' ' . $strUnit;
|
|
}
|
|
|
|
return $strDist;
|
|
}
|
|
|
|
function fxChronotrackApiFormatRaceTeamLabel($arrEntity) {
|
|
foreach (array('team_race', 'is_team_race', 'team') as $strKey) {
|
|
if (!isset($arrEntity[$strKey])) {
|
|
continue;
|
|
}
|
|
$mixVal = $arrEntity[$strKey];
|
|
if ($mixVal === true || $mixVal === 1 || $mixVal === '1' || strtolower((string)$mixVal) === 'true' || strtolower((string)$mixVal) === 'yes') {
|
|
return 'Équipe';
|
|
}
|
|
if ($mixVal === false || $mixVal === 0 || $mixVal === '0' || strtolower((string)$mixVal) === 'false' || strtolower((string)$mixVal) === 'no') {
|
|
return 'Individuel';
|
|
}
|
|
}
|
|
|
|
$strSubtype = strtolower(fxChronotrackApiRaceField($arrEntity, array('race_subtype', 'subtype', 'participant_type')));
|
|
if ($strSubtype !== '') {
|
|
if (strpos($strSubtype, 'team') !== false) {
|
|
return 'Équipe';
|
|
}
|
|
if (strpos($strSubtype, 'individual') !== false || strpos($strSubtype, 'individ') !== false) {
|
|
return 'Individuel';
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiFormatRaceRegChoicesLabel($arrEntity) {
|
|
foreach (array('reg_choice', 'reg_choices', 'registration_choices', 'choices') as $strKey) {
|
|
if (!isset($arrEntity[$strKey]) || !is_array($arrEntity[$strKey])) {
|
|
continue;
|
|
}
|
|
$arrNames = array();
|
|
$arrList = $arrEntity[$strKey];
|
|
if (fxChronotrackApiIsAssocArray($arrList) && (
|
|
isset($arrList['reg_choice_name']) || isset($arrList['name']) || isset($arrList['label'])
|
|
)) {
|
|
$arrList = array($arrList);
|
|
}
|
|
foreach ($arrList as $arrChoice) {
|
|
if (!is_array($arrChoice)) {
|
|
continue;
|
|
}
|
|
$strChoice = fxChronotrackApiRaceField($arrChoice, array(
|
|
'reg_choice_name', 'registration_choice_name', 'choice_name', 'name', 'label',
|
|
));
|
|
if ($strChoice !== '') {
|
|
$arrNames[] = $strChoice;
|
|
}
|
|
}
|
|
if (count($arrNames) > 0) {
|
|
return implode(', ', array_values(array_unique($arrNames)));
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function fxChronotrackApiFormatRaceLabel($arrEntity) {
|
|
$strName = fxChronotrackApiRaceField($arrEntity, array('race_name', 'display_name', 'name', 'title'));
|
|
if ($strName !== '') {
|
|
return $strName;
|
|
}
|
|
|
|
$strTag = fxChronotrackApiRaceField($arrEntity, array('race_tag', 'tag'));
|
|
$strType = fxChronotrackApiRaceField($arrEntity, array('race_type', 'sport', 'race_course_type'));
|
|
$strDist = fxChronotrackApiFormatRaceDistanceLabel($arrEntity);
|
|
$strTeam = fxChronotrackApiFormatRaceTeamLabel($arrEntity);
|
|
$strRegChoice = fxChronotrackApiRaceField($arrEntity, array(
|
|
'reg_choice_name', 'registration_choice_name', 'choice_name', 'reg_choice_label',
|
|
));
|
|
if ($strRegChoice === '') {
|
|
$strRegChoice = fxChronotrackApiFormatRaceRegChoicesLabel($arrEntity);
|
|
}
|
|
|
|
$arrExtras = array();
|
|
if ($strRegChoice !== '' && $strRegChoice !== $strName) {
|
|
$arrExtras[] = $strRegChoice;
|
|
}
|
|
if ($strTag !== '' && $strTag !== $strName && $strTag !== $strRegChoice) {
|
|
$arrExtras[] = 'tag ' . $strTag;
|
|
}
|
|
if ($strType !== '') {
|
|
$arrExtras[] = $strType;
|
|
}
|
|
if ($strDist !== '' && $strDist !== $strName) {
|
|
$arrExtras[] = $strDist;
|
|
}
|
|
if ($strTeam !== '') {
|
|
$arrExtras[] = $strTeam;
|
|
}
|
|
|
|
$arrExtras = array_values(array_unique($arrExtras));
|
|
|
|
if ($strName === '') {
|
|
$strName = $strDist !== '' ? $strDist : ('Race ' . fxChronotrackApiEntityId($arrEntity));
|
|
}
|
|
|
|
if (count($arrExtras) === 0) {
|
|
return $strName;
|
|
}
|
|
|
|
return $strName . ' — ' . implode(' · ', $arrExtras);
|
|
}
|
|
|
|
function fxChronotrackApiEntityStartEpoch($arrEntity) {
|
|
foreach (array(
|
|
'race_planned_start_time', 'race_start_time', 'event_start_time',
|
|
'start_time', 'start_date', 'event_date',
|
|
) as $strKey) {
|
|
if (!isset($arrEntity[$strKey]) || $arrEntity[$strKey] === '' || $arrEntity[$strKey] === null) {
|
|
continue;
|
|
}
|
|
$mixVal = $arrEntity[$strKey];
|
|
if (is_numeric($mixVal)) {
|
|
return intval($mixVal);
|
|
}
|
|
$intTs = strtotime((string)$mixVal);
|
|
if ($intTs !== false) {
|
|
return $intTs;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function fxChronotrackApiFormatEventRow($arrEntity) {
|
|
$intStart = fxChronotrackApiEntityStartEpoch($arrEntity);
|
|
return array(
|
|
'ct_event_id' => fxChronotrackApiEntityId($arrEntity),
|
|
'name' => fxChronotrackApiEntityName($arrEntity),
|
|
'start_epoch' => $intStart,
|
|
'start_label' => $intStart > 0 ? date('Y-m-d H:i', $intStart) : '',
|
|
'is_past' => ($intStart > 0 && $intStart < strtotime('today')),
|
|
'raw' => $arrEntity,
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiFetchEventsRaw() {
|
|
$arrApi = fxChronotrackApiOAuthApiGet('event');
|
|
if ($arrApi['state'] !== 'ok') {
|
|
return $arrApi;
|
|
}
|
|
|
|
$arrList = fxChronotrackApiNormalizeEntityList($arrApi['json'], 'event');
|
|
$arrRows = array();
|
|
foreach ($arrList as $arrEntity) {
|
|
if (!is_array($arrEntity)) {
|
|
continue;
|
|
}
|
|
$arrRow = fxChronotrackApiFormatEventRow($arrEntity);
|
|
if ($arrRow['ct_event_id'] === '') {
|
|
continue;
|
|
}
|
|
$arrRows[] = $arrRow;
|
|
}
|
|
|
|
return array('state' => 'ok', 'events' => $arrRows);
|
|
}
|
|
|
|
function fxChronotrackApiFilterEvents($arrEvents, $strSearch = '', $blnShowPast = false) {
|
|
$strSearch = mb_strtolower(trim($strSearch), 'UTF-8');
|
|
$arrFiltered = array();
|
|
|
|
foreach ($arrEvents as $arrEvent) {
|
|
if (!$blnShowPast && !empty($arrEvent['is_past'])) {
|
|
continue;
|
|
}
|
|
if ($strSearch !== '') {
|
|
$strHay = mb_strtolower($arrEvent['name'] . ' ' . $arrEvent['ct_event_id'], 'UTF-8');
|
|
if (mb_strpos($strHay, $strSearch, 0, 'UTF-8') === false) {
|
|
continue;
|
|
}
|
|
}
|
|
$arrFiltered[] = $arrEvent;
|
|
}
|
|
|
|
usort($arrFiltered, function ($a, $b) {
|
|
$intA = intval($a['start_epoch']);
|
|
$intB = intval($b['start_epoch']);
|
|
if ($intA === $intB) {
|
|
return strcasecmp($a['name'], $b['name']);
|
|
}
|
|
if ($intA <= 0) {
|
|
return 1;
|
|
}
|
|
if ($intB <= 0) {
|
|
return -1;
|
|
}
|
|
return ($intA < $intB) ? -1 : 1;
|
|
});
|
|
|
|
return $arrFiltered;
|
|
}
|
|
|
|
function fxChronotrackApiFetchEventsFiltered($strSearch = '', $blnShowPast = false) {
|
|
$arrRaw = fxChronotrackApiFetchEventsRaw();
|
|
if ($arrRaw['state'] !== 'ok') {
|
|
return $arrRaw;
|
|
}
|
|
return array(
|
|
'state' => 'ok',
|
|
'events' => fxChronotrackApiFilterEvents($arrRaw['events'], $strSearch, $blnShowPast),
|
|
'total' => count($arrRaw['events']),
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiEntityBelongsToEvent($arrEntity, $intCtEventId) {
|
|
if ($intCtEventId <= 0) {
|
|
return true;
|
|
}
|
|
foreach (array('event_id', 'event') as $strKey) {
|
|
if (!isset($arrEntity[$strKey])) {
|
|
continue;
|
|
}
|
|
$mixVal = $arrEntity[$strKey];
|
|
if (is_array($mixVal)) {
|
|
$mixVal = $mixVal['event_id'] ?? $mixVal['id'] ?? null;
|
|
}
|
|
if ($mixVal !== null && $mixVal !== '' && intval($mixVal) !== $intCtEventId) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function fxChronotrackApiFormatRegChoiceRow($arrEntity) {
|
|
$strName = fxChronotrackApiRaceField($arrEntity, array(
|
|
'reg_choice_name', 'registration_choice_name', 'choice_name', 'display_name', 'name', 'title',
|
|
));
|
|
$intParentRaceId = intval(fxChronotrackApiRaceField($arrEntity, array('race_id')));
|
|
|
|
$arrExtras = array();
|
|
if (isset($arrEntity['race']) && is_array($arrEntity['race'])) {
|
|
$strRaceName = fxChronotrackApiEntityName($arrEntity['race']);
|
|
$strDist = fxChronotrackApiFormatRaceDistanceLabel($arrEntity['race']);
|
|
if ($strRaceName !== '' && strcasecmp($strRaceName, $strName) !== 0) {
|
|
$arrExtras[] = $strRaceName;
|
|
} elseif ($strDist !== '' && stripos($strName, $strDist) === false) {
|
|
$arrExtras[] = $strDist;
|
|
}
|
|
$strTeam = fxChronotrackApiFormatRaceTeamLabel($arrEntity['race']);
|
|
if ($strTeam !== '') {
|
|
$arrExtras[] = $strTeam;
|
|
}
|
|
}
|
|
|
|
$strLabel = $strName;
|
|
if ($strLabel === '') {
|
|
$strLabel = 'Choix d\'inscription ' . fxChronotrackApiEntityId($arrEntity);
|
|
} elseif (count($arrExtras) > 0) {
|
|
$strLabel .= ' · ' . implode(' · ', array_values(array_unique($arrExtras)));
|
|
}
|
|
|
|
return array(
|
|
'ct_race_id' => fxChronotrackApiEntityId($arrEntity),
|
|
'kind' => 'reg_choice',
|
|
'name' => $strName !== '' ? $strName : $strLabel,
|
|
'label' => $strLabel,
|
|
'parent_race_id' => $intParentRaceId > 0 ? $intParentRaceId : null,
|
|
'start_label' => '',
|
|
'raw' => $arrEntity,
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiCollectRegChoiceEntities($mixPayload) {
|
|
$arrById = array();
|
|
if (!is_array($mixPayload)) {
|
|
return array();
|
|
}
|
|
|
|
$arrScopes = array($mixPayload);
|
|
if (isset($mixPayload['event']) && is_array($mixPayload['event'])) {
|
|
$arrScopes[] = $mixPayload['event'];
|
|
}
|
|
|
|
foreach ($arrScopes as $arrScope) {
|
|
if (!is_array($arrScope)) {
|
|
continue;
|
|
}
|
|
|
|
$arrList = fxChronotrackApiNormalizeEntityList($arrScope, 'reg_choice');
|
|
foreach ($arrList as $arrEntity) {
|
|
if (!is_array($arrEntity) || !isset($arrEntity['reg_choice_id'])) {
|
|
continue;
|
|
}
|
|
$strId = (string)$arrEntity['reg_choice_id'];
|
|
$arrById[$strId] = $arrEntity;
|
|
}
|
|
|
|
$arrRaces = fxChronotrackApiNormalizeEntityList($arrScope, 'race');
|
|
foreach ($arrRaces as $arrRace) {
|
|
if (!is_array($arrRace) || !isset($arrRace['race_id'])) {
|
|
continue;
|
|
}
|
|
$arrChoices = fxChronotrackApiNormalizeEntityList($arrRace, 'reg_choice');
|
|
foreach ($arrChoices as $arrChoice) {
|
|
if (!is_array($arrChoice) || !isset($arrChoice['reg_choice_id'])) {
|
|
continue;
|
|
}
|
|
$strId = (string)$arrChoice['reg_choice_id'];
|
|
if (!isset($arrChoice['race']) || !is_array($arrChoice['race'])) {
|
|
$arrChoice['race'] = $arrRace;
|
|
}
|
|
$arrById[$strId] = $arrChoice;
|
|
}
|
|
}
|
|
}
|
|
|
|
return array_values($arrById);
|
|
}
|
|
|
|
function fxChronotrackApiCollectRaceEntities($mixPayload) {
|
|
$arrById = array();
|
|
if (!is_array($mixPayload)) {
|
|
return array();
|
|
}
|
|
|
|
$arrScopes = array($mixPayload);
|
|
if (isset($mixPayload['event']) && is_array($mixPayload['event'])) {
|
|
$arrScopes[] = $mixPayload['event'];
|
|
}
|
|
|
|
foreach ($arrScopes as $arrScope) {
|
|
if (!is_array($arrScope)) {
|
|
continue;
|
|
}
|
|
$arrList = fxChronotrackApiNormalizeEntityList($arrScope, 'race');
|
|
foreach ($arrList as $arrEntity) {
|
|
if (!is_array($arrEntity) || !isset($arrEntity['race_id'])) {
|
|
continue;
|
|
}
|
|
$strId = (string)$arrEntity['race_id'];
|
|
$arrById[$strId] = $arrEntity;
|
|
}
|
|
}
|
|
|
|
return array_values($arrById);
|
|
}
|
|
|
|
function fxChronotrackApiParseRegChoiceRowsFromPayload($mixPayload, $intCtEventId = 0) {
|
|
$arrRows = array();
|
|
$arrEntities = fxChronotrackApiCollectRegChoiceEntities($mixPayload);
|
|
|
|
foreach ($arrEntities as $arrEntity) {
|
|
if ($intCtEventId > 0 && !fxChronotrackApiEntityBelongsToEvent($arrEntity, $intCtEventId)) {
|
|
continue;
|
|
}
|
|
$arrRow = fxChronotrackApiFormatRegChoiceRow($arrEntity);
|
|
if ($arrRow['ct_race_id'] === '') {
|
|
continue;
|
|
}
|
|
$arrRows[$arrRow['ct_race_id']] = $arrRow;
|
|
}
|
|
|
|
$arrRows = array_values($arrRows);
|
|
usort($arrRows, function ($a, $b) {
|
|
return strcasecmp($a['name'], $b['name']);
|
|
});
|
|
|
|
return $arrRows;
|
|
}
|
|
|
|
function fxChronotrackApiFetchRegChoicesForEvent($intCtEventId) {
|
|
$intCtEventId = intval($intCtEventId);
|
|
if ($intCtEventId <= 0) {
|
|
return array('state' => 'error', 'message' => 'event_id CT invalide');
|
|
}
|
|
|
|
$arrApi = fxChronotrackApiOAuthApiGet('event/' . $intCtEventId);
|
|
if ($arrApi['state'] !== 'ok') {
|
|
return array(
|
|
'state' => 'error',
|
|
'message' => $arrApi['message'] ?? 'Impossible de lire l\'événement ChronoTrack',
|
|
);
|
|
}
|
|
|
|
$arrRows = fxChronotrackApiParseRegChoiceRowsFromPayload($arrApi['json'], $intCtEventId);
|
|
if (count($arrRows) > 0) {
|
|
return array(
|
|
'state' => 'ok',
|
|
'races' => $arrRows,
|
|
'source' => 'event/' . $intCtEventId,
|
|
'kind' => 'reg_choice',
|
|
);
|
|
}
|
|
|
|
return array('state' => 'ok', 'races' => array(), 'kind' => 'reg_choice');
|
|
}
|
|
|
|
function fxChronotrackApiFormatRaceRow($arrEntity) {
|
|
$intStart = fxChronotrackApiEntityStartEpoch($arrEntity);
|
|
$strLabel = fxChronotrackApiFormatRaceLabel($arrEntity);
|
|
return array(
|
|
'ct_race_id' => fxChronotrackApiEntityId($arrEntity),
|
|
'kind' => 'race',
|
|
'name' => fxChronotrackApiEntityName($arrEntity),
|
|
'label' => $strLabel,
|
|
'race_tag' => fxChronotrackApiRaceField($arrEntity, array('race_tag', 'tag')),
|
|
'race_type' => fxChronotrackApiRaceField($arrEntity, array('race_type', 'sport')),
|
|
'distance' => fxChronotrackApiFormatRaceDistanceLabel($arrEntity),
|
|
'team_mode' => fxChronotrackApiFormatRaceTeamLabel($arrEntity),
|
|
'start_label' => $intStart > 0 ? date('Y-m-d H:i', $intStart) : '',
|
|
'raw' => $arrEntity,
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiParseRaceRowsFromPayload($mixPayload, $intCtEventId = 0) {
|
|
$arrRows = array();
|
|
$arrEntities = fxChronotrackApiCollectRaceEntities($mixPayload);
|
|
|
|
foreach ($arrEntities as $arrEntity) {
|
|
if ($intCtEventId > 0 && !fxChronotrackApiEntityBelongsToEvent($arrEntity, $intCtEventId)) {
|
|
continue;
|
|
}
|
|
$arrRow = fxChronotrackApiFormatRaceRow($arrEntity);
|
|
if ($arrRow['ct_race_id'] === '') {
|
|
continue;
|
|
}
|
|
$arrRows[$arrRow['ct_race_id']] = $arrRow;
|
|
}
|
|
|
|
$arrRows = array_values($arrRows);
|
|
usort($arrRows, function ($a, $b) {
|
|
return strcasecmp($a['name'], $b['name']);
|
|
});
|
|
|
|
return $arrRows;
|
|
}
|
|
|
|
function fxChronotrackApiFetchRacesForEvent($intCtEventId) {
|
|
$intCtEventId = intval($intCtEventId);
|
|
if ($intCtEventId <= 0) {
|
|
return array('state' => 'error', 'message' => 'event_id CT invalide');
|
|
}
|
|
|
|
if (!fxChronotrackApiSettingsConfigured()) {
|
|
return array('state' => 'error', 'message' => fxChronotrackApiSettingsErrorMessage());
|
|
}
|
|
|
|
$strRacePath = 'event/' . $intCtEventId . '/race';
|
|
$arrApi = fxChronotrackApiOAuthApiGet($strRacePath);
|
|
if ($arrApi['state'] !== 'ok') {
|
|
return array(
|
|
'state' => 'error',
|
|
'message' => $arrApi['message'] ?? 'Impossible de lire les courses ChronoTrack',
|
|
);
|
|
}
|
|
|
|
$arrRaceRows = fxChronotrackApiParseRaceRowsFromPayload($arrApi['json'], $intCtEventId);
|
|
if (count($arrRaceRows) > 0) {
|
|
return array(
|
|
'state' => 'ok',
|
|
'races' => $arrRaceRows,
|
|
'source' => $strRacePath,
|
|
'kind' => 'race',
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'state' => 'ok',
|
|
'races' => array(),
|
|
'kind' => 'race',
|
|
'message' => 'Aucune course dans GET ' . $strRacePath
|
|
. ' (clé attendue : event_race).',
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiDiagnosticEntitySamples($mixPayload, $strEntityKey, $intMax = 8) {
|
|
if ($strEntityKey === 'reg_choice') {
|
|
$arrEntities = fxChronotrackApiCollectRegChoiceEntities($mixPayload);
|
|
} elseif ($strEntityKey === 'race') {
|
|
$arrEntities = fxChronotrackApiCollectRaceEntities($mixPayload);
|
|
} elseif ($strEntityKey === 'entry') {
|
|
$arrEntities = fxChronotrackApiNormalizeEntityList($mixPayload, 'entry');
|
|
} else {
|
|
$arrEntities = fxChronotrackApiNormalizeEntityList($mixPayload, $strEntityKey);
|
|
}
|
|
|
|
$arrSamples = array();
|
|
foreach ($arrEntities as $arrEntity) {
|
|
if (!is_array($arrEntity)) {
|
|
continue;
|
|
}
|
|
if ($strEntityKey === 'entry') {
|
|
$strId = fxChronotrackApiEntityId($arrEntity);
|
|
if ($strId === '') {
|
|
$strId = fxChronotrackApiEntityExternalId($arrEntity);
|
|
}
|
|
if ($strId === '') {
|
|
continue;
|
|
}
|
|
$arrSamples[$strId] = array(
|
|
'id' => $strId,
|
|
'external_id' => fxChronotrackApiEntityExternalId($arrEntity),
|
|
'name' => fxChronotrackApiEntityEntryLabel($arrEntity),
|
|
'bib' => fxChronotrackApiRaceField($arrEntity, array('bib', 'bib_number', 'entry_bib')),
|
|
'entry_status'=> fxChronotrackApiRaceField($arrEntity, array('entry_status', 'status')),
|
|
'race_id' => fxChronotrackApiRaceField($arrEntity, array('race_id', 'event_race_id')),
|
|
'country_code'=> fxChronotrackApiRaceField($arrEntity, array('country_code', 'country', 'country_iso')),
|
|
'state_code' => fxChronotrackApiRaceField($arrEntity, array('state_code', 'state', 'province_code')),
|
|
'keys' => array_slice(array_keys($arrEntity), 0, 32),
|
|
);
|
|
continue;
|
|
}
|
|
|
|
$strId = fxChronotrackApiEntityId($arrEntity);
|
|
if ($strId === '') {
|
|
continue;
|
|
}
|
|
$arrSamples[$strId] = array(
|
|
'id' => $strId,
|
|
'name' => fxChronotrackApiEntityName($arrEntity),
|
|
'keys' => array_slice(array_keys($arrEntity), 0, 24),
|
|
);
|
|
}
|
|
|
|
$arrSamples = array_values($arrSamples);
|
|
return array(
|
|
'count' => count($arrSamples),
|
|
'samples' => array_slice($arrSamples, 0, $intMax),
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiDiagnosticSummarizeEntryPayload($mixJson) {
|
|
if (!is_array($mixJson)) {
|
|
return array(
|
|
'top_keys' => array(),
|
|
'entry' => array('count' => 0, 'samples' => array(), 'field_keys' => array()),
|
|
);
|
|
}
|
|
|
|
$arrEntry = fxChronotrackApiDiagnosticEntitySamples($mixJson, 'entry', 5);
|
|
$arrFieldKeys = array();
|
|
if (!empty($arrEntry['samples'][0]['keys'])) {
|
|
$arrFieldKeys = $arrEntry['samples'][0]['keys'];
|
|
}
|
|
|
|
return array(
|
|
'top_keys' => array_slice(array_keys($mixJson), 0, 40),
|
|
'entry' => $arrEntry,
|
|
'field_keys' => $arrFieldKeys,
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiDiagnosticSummarizePayload($mixJson) {
|
|
if (!is_array($mixJson)) {
|
|
return array(
|
|
'top_keys' => array(),
|
|
'reg_choice' => array('count' => 0, 'samples' => array()),
|
|
'race' => array('count' => 0, 'samples' => array()),
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'top_keys' => array_slice(array_keys($mixJson), 0, 40),
|
|
'event_race' => fxChronotrackApiDiagnosticEntitySamples(
|
|
is_array($mixJson) && isset($mixJson['event_race']) ? array('event_race' => $mixJson['event_race']) : $mixJson,
|
|
'race'
|
|
),
|
|
'reg_choice' => fxChronotrackApiDiagnosticEntitySamples($mixJson, 'reg_choice'),
|
|
'race' => fxChronotrackApiDiagnosticEntitySamples($mixJson, 'race'),
|
|
);
|
|
}
|
|
|
|
function fxChronotrackApiDiagnosticEncodeJson($mixJson) {
|
|
$strRaw = json_encode($mixJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
if (!is_string($strRaw)) {
|
|
return '(json_encode a échoué)';
|
|
}
|
|
if (strlen($strRaw) > 48000) {
|
|
return substr($strRaw, 0, 48000) . "\n\n... [tronqué — " . strlen($strRaw) . ' octets au total]';
|
|
}
|
|
return $strRaw;
|
|
}
|
|
|
|
function fxChronotrackApiRunEventDiagnostic($intCtEventId) {
|
|
$intCtEventId = intval($intCtEventId);
|
|
if ($intCtEventId <= 0) {
|
|
return array('state' => 'error', 'message' => 'ct_event_id manquant');
|
|
}
|
|
if (!fxChronotrackApiSettingsConfigured()) {
|
|
return array('state' => 'error', 'message' => fxChronotrackApiSettingsErrorMessage());
|
|
}
|
|
|
|
$arrToken = fxChronotrackApiOAuthFetchToken(false);
|
|
if ($arrToken['state'] !== 'ok') {
|
|
return array('state' => 'error', 'message' => 'OAuth : ' . ($arrToken['message'] ?? 'échec'));
|
|
}
|
|
|
|
$arrPaths = array(
|
|
array('path' => 'event/' . $intCtEventId . '/race'),
|
|
array('path' => 'event/' . $intCtEventId . '/entry', 'query' => array('page' => 1, 'page_size' => 5)),
|
|
array('path' => 'event/' . $intCtEventId),
|
|
array('path' => 'event/' . $intCtEventId . '/reg_choice'),
|
|
);
|
|
|
|
$arrProbes = array();
|
|
foreach ($arrPaths as $arrPathDef) {
|
|
$strPath = $arrPathDef['path'];
|
|
$arrQuery = isset($arrPathDef['query']) ? $arrPathDef['query'] : array();
|
|
$arrApi = fxChronotrackApiOAuthApiGet($strPath, $arrQuery);
|
|
$arrProbe = array(
|
|
'path' => $strPath,
|
|
'query' => $arrQuery,
|
|
'state' => $arrApi['state'] ?? 'error',
|
|
'http_code' => intval($arrApi['http_code'] ?? $arrApi['http']['http_code'] ?? 0),
|
|
'message' => $arrApi['message'] ?? '',
|
|
'summary' => array(),
|
|
'raw_json' => '',
|
|
);
|
|
if ($arrApi['state'] === 'ok') {
|
|
if (strpos($strPath, '/entry') !== false) {
|
|
$arrProbe['summary'] = fxChronotrackApiDiagnosticSummarizeEntryPayload($arrApi['json']);
|
|
} else {
|
|
$arrProbe['summary'] = fxChronotrackApiDiagnosticSummarizePayload($arrApi['json']);
|
|
}
|
|
$arrProbe['raw_json'] = fxChronotrackApiDiagnosticEncodeJson($arrApi['json']);
|
|
} elseif (isset($arrApi['http']['body']) && trim((string)$arrApi['http']['body']) !== '') {
|
|
$arrProbe['raw_json'] = substr(trim((string)$arrApi['http']['body']), 0, 8000);
|
|
}
|
|
$arrProbes[] = $arrProbe;
|
|
}
|
|
|
|
return array(
|
|
'state' => 'ok',
|
|
'ct_event_id' => $intCtEventId,
|
|
'oauth' => !empty($arrToken['from_cache']) ? 'token en cache' : 'token renouvelé',
|
|
'probes' => $arrProbes,
|
|
'generated_at'=> date('c'),
|
|
);
|
|
}
|