diff --git a/examples/data.php b/examples/data.php new file mode 100644 index 0000000..6d41c12 --- /dev/null +++ b/examples/data.php @@ -0,0 +1,279 @@ + OAUTH2_CLIENT_ID, + 'redirect_uri' => $scriptPath, + 'scope' => 'read', + 'state' => $_SESSION['state'], + 'response_type' => 'code' + ); + + # Redirect the user to Github's authorization page + header('Location: ' . $authorizeURL . '?' . http_build_query($params)); + die(); +} + +# When Github redirects the user back here, there will be a "code" and "state" parameter in the query string + +if (get('code')) { + # Verify the state matches our stored state + if (!get('state') || $_SESSION['state'] != get('state')) { + header('Location: ' . $scriptPath); + die(); + } + + # Exchange the auth code for a token + $token = apiRequest($tokenURL, array( + 'client_id' => OAUTH2_CLIENT_ID, + 'client_secret' => OAUTH2_CLIENT_SECRET, + 'redirect_uri' => $scriptPath, + 'state' => $_SESSION['state'], + 'code' => get('code'), + 'grant_type' => 'authorization_code' + )); + $_SESSION['access_token'] = $token->access_token; + + header('Location: ' . $scriptPath); +} + +if (session('access_token')) { + + # ========= + # WELCOME! + # ========= + + $stepics = apiRequest($apiURLBase . 'stepics/1'); + $user_id = $stepics->profiles[0]->id; + $first_name = $stepics->profiles[0]->first_name; + $last_name = $stepics->profiles[0]->last_name; + echo ''; + echo 'Личный кабинет онлайн-программы «Анализ данных»'; + echo ''; + echo ''; + echo ''; + echo '

Личный кабинет онлайн-программы «Анализ данных» на Stepik.org

'; + echo '

Добро пожаловать, ' . $first_name . ' ' . $last_name . '!

'; + echo '
'; + + # ============= + # COURSES LIST + # ============= + + $courses = array( + array('id' => 217, 'required' => True, 'sections' => array(2, 4), 'need_to_pass' => 85, 'exams' => 1536), # Алгоритмы: теория и практика. Методы + array('id' => 129, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 85, 'exams' => 1425), # Анализ данных в R + array('id' => 724, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 85, 'exams' => null), # Анализ данных в R. Часть 2 + array('id' => 1240, 'required' => True, 'sections' => array(1, 2, 5, 6), 'need_to_pass' => 85, 'exams' => 1534), # Введение в базы данных + array('id' => 253, 'required' => True, 'sections' => array(1, 3, 4, 5), 'need_to_pass' => 85, 'exams' => 1535), # Введение в архитектуру ЭВМ. Элементы операционных систем. + array('id' => 902, 'required' => True, 'sections' => array(1, 2, 3, 4), 'need_to_pass' => 90, 'exams' => 1424), # Дискретная математика + array('id' => 73, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 90, 'exams' => 1427), # Введение в Linux + array('id' => 497, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 85, 'exams' => 1426), # Основы программирования на R + array('id' => 76, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 90, 'exams' => 1423), # Основы статистики + array('id' => 524, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 85, 'exams' => null), # Основы статистики. Часть 2 + array('id' => 67, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 90, 'exams' => 1428), # Программирование на Python + array('id' => 512, 'required' => True, 'sections' => array(1, 2, 3), 'need_to_pass' => 90, 'exams' => null), # Python: основы и применение + array('id' => 217, 'required' => False, 'sections' => array(6, 8), 'need_to_pass' => 85, 'exams' => 1537), # Алгоритмы: теория и практика. Методы + array('id' => 253, 'required' => False, 'sections' => array(2, 6, 7), 'need_to_pass' => 85, 'exams' => 1538), # Введение в архитектуру ЭВМ. Элементы операционных систем. + array('id' => 1240, 'required' => False, 'sections' => array(3, 4, 7), 'need_to_pass' => 85, 'exams' => 1544), # Введение в базы данных + array('id' => 95, 'required' => False, 'sections' => array(1, 2, 3, 4), 'need_to_pass' => 85, 'exams' => 1429), # Введение в математический анализ + array('id' => 401, 'required' => False, 'sections' => array(1, 2, 3, 4), 'need_to_pass' => 85, 'exams' => 1432), # Нейронные сети + array('id' => 7, 'required' => False, 'sections' => array(1, 2, 3, 4, 5, 6), 'need_to_pass' => 85, 'exams' => 1430), # Программирование на языке C++ + array('id' => 187, 'required' => False, 'sections' => array(1, 2, 3, 4, 5, 6), 'need_to_pass' => 85, 'exams' => 1431), # Java. Базовый курс + # TO ADD WHEN READY: Управление вычислениями (required) + # TO ADD WHEN READY: Основы статистики, часть 3 (not required) + # TO ADD WHEN READY: Machine Learning (not required) + ); + + echo '

Курсы программы (взаимосвязи):

'; + echo ''; + echo ''; + echo ''; + + $previousCourse = null; + foreach ($courses as $course) { + $info = apiRequest($apiURLBase . 'courses/' . $course['id'])->courses[0]; + $section_ids = array(); + foreach ($course['sections'] as $i) { + $section_ids[] = $info->sections[$i - 1]; + } + $sections = apiRequest($apiURLBase . 'sections?ids[]=' . implode('&ids[]=', $section_ids))->sections; + $progress_ids = array(); + foreach ($sections as $section) { + $progress_ids[] = $section->progress; + } + $progresses = apiRequest($apiURLBase . 'progresses?ids[]=' . implode('&ids[]=', $progress_ids))->progresses; + $score = 0; + $cost = 0; + foreach ($progresses as $progress) { + $score += $progress->score; + $cost += $progress->cost; + } + + $percentage = $cost ? round(100 * $score / $cost, 2) : 0; + if ($percentage >= $course['need_to_pass']) { + try { + $exam = apiRequest($apiURLBase . 'courses/' . $course['exams'])->courses[0]; + $progress = apiRequest($apiURLBase . 'progresses/' . $exam->progress)->progresses[0]; + $exam_message = $progress->score . ' / ' . $progress->cost; + } catch (Exception $e) { + $exam_message = 'можно начать'; + } + } else { + $exam_message = 'нет доступа (нужно ' . $course['need_to_pass'] . '% за курс)'; + } + if ($previousCourse['required'] and !$course['required']) { + echo ''; + echo ''; + } + + echo ''; + echo ''; + echo ''; + echo ''; + + if ($cost) { + echo ''; + echo ''; + } else { + echo ''; + } + + echo ''; + echo ''; + $previousCourse = $course; + } + + echo '
Обязательные курсы:
КурсКоличество
модулей
МодулиВаши баллыВаш процентДопуск к экзамену
Курсы по выбору:
КурсКоличество
модулей
МодулиВаши баллыВаш процентЭкзамен
' . $info->title . '' . count($course['sections']) . '' . implode(", ", $course['sections']) . '' . $score . ' / ' . $cost . '' . $percentage . '%Запишитесь на курс' . $exam_message . '
'; + + # ============= + # PAYMENTS LOG + # ============= + + $subscription_plans = array(10 => 0, 1999 => 1, 5397 => 3, 6000 => 3, 9595 => 6, 16791 => 12); + $format = 'M d, Y (H:i)'; + $page = 1; + $payments_list = array(); + $payment_start = 0; + $payment_valid_until = 0; + do { + $payments = apiRequest($apiURLBase . 'payments?page=' . $page); + foreach ($payments->payments as $payment) { + if ($payment->destination_type != 'au_data') { + continue; + } + + $payment_date = strtotime($payment->payment_date); + $payment_start = max($payment_date, $payment_start); + $months = $subscription_plans[intval($payment->amount)]; + $payment_valid_until = paymentDue($payment_start, $months); + $payments_list[] = array( + intval($payment->amount), + date($format, $payment_date), + date($format, $payment_start), + date($format, $payment_valid_until) + ); + $payment_start = $payment_valid_until; + } + $page += 1; + } while ($payments->meta->has_next); + + if ($payment_valid_until >= time()) { + $color = ($payment_valid_until - time() >= 60 * 60 * 24 * 7) ? "#66cc66" : "cccc00"; # yellow if less than one week left + echo '

Ваша подписка на программу  активна до ' . date($format, $payment_valid_until) . ' 

'; + } else { + echo '

Ваша подписка на программу  не активна 

'; + } + + echo '

Ваши платежи:

'; + echo ''; + echo ''; + foreach (array_reverse($payments_list) as $payment) { + echo ''; + } + echo '
Сумма (руб)Дата и время платежа (UTC)Действует отДействует до
'; + echo implode('', $payment); + echo '
'; + + # LOGOUT + echo '

[Выйти из кабинета]

'; + echo ''; +} else { + echo '

Личный кабинет онлайн-программы «Анализ данных» на Stepik.org

'; + echo '

Вы не вошли

'; + echo '

Войти через Stepik.org

'; +} + +# ================= +# HELPER FUNCTIONS +# ================= + +function apiRequest($url, $post = FALSE, $headers = array()) +{ + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + + if ($post) + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); + + $headers[] = 'Accept: application/json'; + + if (session('access_token')) + $headers[] = 'Authorization: Bearer ' . session('access_token'); + + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $response = curl_exec($ch); + return json_decode($response); +} + +function get($key, $default = NULL) +{ + return array_key_exists($key, $_GET) ? $_GET[$key] : $default; +} + +function session($key, $default = NULL) +{ + return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default; +} + +# Based on http://stackoverflow.com/a/24014541/92396 but fixed and simplified: +function paymentDue($timestamp, $months) +{ + $date = new DateTime('@' . $timestamp); + $next = clone $date; + $next->modify('last day of +' . $months . ' month'); + if ($date->format('d') > $next->format('d')) { + $add = $date->diff($next); + } else { + $add = new DateInterval('P' . $months . 'M'); + } + $newDate = $date->add($add); + return $newDate->getTimestamp(); +}